blob: 26dd9783b74d0f96ad51f23c9efd35b68bc703e5 [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
Rob Landley688ed0d2006-03-04 22:40:25 +0000519#if BB_LITTLE_ENDIAN
520# define ELFDATAM ELFDATA2LSB
521#else
522# define ELFDATAM ELFDATA2MSB
Eric Andersenb1591d12002-04-12 00:28:59 +0000523#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000524
Eric Andersen9f16d612000-06-12 23:11:16 +0000525#ifndef ElfW
526# if ELFCLASSM == ELFCLASS32
527# define ElfW(x) Elf32_ ## x
528# define ELFW(x) ELF32_ ## x
529# else
530# define ElfW(x) Elf64_ ## x
531# define ELFW(x) ELF64_ ## x
532# endif
533#endif
534
Eric Andersen85e5e722003-07-22 08:56:55 +0000535/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000536#ifndef ELF32_ST_INFO
537# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
538#endif
539
540#ifndef ELF64_ST_INFO
541# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
542#endif
543
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000544#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
545#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
546#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
547#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
548#define ELF_R_SYM(val) ELFW(R_SYM)(val)
549
Eric Andersen9f16d612000-06-12 23:11:16 +0000550struct obj_string_patch;
551struct obj_symbol_patch;
552
553struct obj_section
554{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000555 ElfW(Shdr) header;
556 const char *name;
557 char *contents;
558 struct obj_section *load_next;
559 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000560};
561
562struct obj_symbol
563{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000564 struct obj_symbol *next; /* hash table link */
565 const char *name;
566 unsigned long value;
567 unsigned long size;
568 int secidx; /* the defining section index/module */
569 int info;
570 int ksymidx; /* for export to the kernel symtab */
571 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000572};
573
574/* Hardcode the hash table size. We shouldn't be needing so many
575 symbols that we begin to degrade performance, and we get a big win
576 by giving the compiler a constant divisor. */
577
578#define HASH_BUCKETS 521
579
580struct obj_file
581{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000582 ElfW(Ehdr) header;
583 ElfW(Addr) baseaddr;
584 struct obj_section **sections;
585 struct obj_section *load_order;
586 struct obj_section **load_order_search_start;
587 struct obj_string_patch *string_patches;
588 struct obj_symbol_patch *symbol_patches;
589 int (*symbol_cmp)(const char *, const char *);
590 unsigned long (*symbol_hash)(const char *);
591 unsigned long local_symtab_size;
592 struct obj_symbol **local_symtab;
593 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000594};
595
596enum obj_reloc
597{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000598 obj_reloc_ok,
599 obj_reloc_overflow,
600 obj_reloc_dangerous,
601 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000602};
603
604struct obj_string_patch
605{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000606 struct obj_string_patch *next;
607 int reloc_secidx;
608 ElfW(Addr) reloc_offset;
609 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000610};
611
612struct obj_symbol_patch
613{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000614 struct obj_symbol_patch *next;
615 int reloc_secidx;
616 ElfW(Addr) reloc_offset;
617 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000618};
619
620
621/* Generic object manipulation routines. */
622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000628 const char *name);
629
Eric Andersen044228d2001-07-17 01:12:36 +0000630static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000631 struct obj_symbol *sym);
632
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000633#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000634static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000635 int (*cmp)(const char *, const char *),
636 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000637#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000640 const char *name);
641
Eric Andersen044228d2001-07-17 01:12:36 +0000642static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000643 struct obj_section *sec);
644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000646 const char *name,
647 unsigned long align,
648 unsigned long size);
649
Eric Andersen044228d2001-07-17 01:12:36 +0000650static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000651 const char *name,
652 unsigned long align,
653 unsigned long size);
654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000658 const char *string);
659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000661 struct obj_symbol *sym);
662
Eric Andersen044228d2001-07-17 01:12:36 +0000663static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000664
Eric Andersen044228d2001-07-17 01:12:36 +0000665static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000666
Eric Andersen044228d2001-07-17 01:12:36 +0000667static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000668
Eric Andersen044228d2001-07-17 01:12:36 +0000669static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000670
Eric Andersen044228d2001-07-17 01:12:36 +0000671static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000672
Eric Andersen044228d2001-07-17 01:12:36 +0000673static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000674
675/* Architecture specific manipulation routines. */
676
Eric Andersen044228d2001-07-17 01:12:36 +0000677static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000678
Eric Andersen044228d2001-07-17 01:12:36 +0000679static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000680
Eric Andersen044228d2001-07-17 01:12:36 +0000681static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000682
Eric Andersen044228d2001-07-17 01:12:36 +0000683static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000684 struct obj_section *targsec,
685 struct obj_section *symsec,
686 struct obj_symbol *sym,
687 ElfW(RelM) *rel, ElfW(Addr) value);
688
Eric Andersencffd5022002-05-24 06:50:15 +0000689static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000690
Glenn L McGrath759515c2003-08-30 06:00:33 +0000691static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000692
Eric Andersen9f16d612000-06-12 23:11:16 +0000693#endif /* obj.h */
694//----------------------------------------------------------------------------
695//--------end of modutils obj.h
696//----------------------------------------------------------------------------
697
698
Miles Baderae28b042002-04-01 09:34:25 +0000699/* SPFX is always a string, so it can be concatenated to string constants. */
700#ifdef SYMBOL_PREFIX
701#define SPFX SYMBOL_PREFIX
702#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000703#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000704#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000705
Erik Andersen02104321999-12-17 18:57:34 +0000706
Erik Andersend387d011999-12-21 02:55:11 +0000707#define _PATH_MODULES "/lib/modules"
Rob Landleybc68cd12006-03-10 19:22:06 +0000708enum { STRVERSIONLEN = 32 };
Erik Andersend387d011999-12-21 02:55:11 +0000709
Eric Andersen9f16d612000-06-12 23:11:16 +0000710/*======================================================================*/
711
Eric Andersen044228d2001-07-17 01:12:36 +0000712static int flag_force_load = 0;
713static int flag_autoclean = 0;
714static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000715static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000716static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000717
718
719/*======================================================================*/
720
Eric Andersencffd5022002-05-24 06:50:15 +0000721#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000722
Eric Andersencffd5022002-05-24 06:50:15 +0000723struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000724{
Eric Andersencffd5022002-05-24 06:50:15 +0000725 struct arch_list_entry *next;
726 CONFIG_LIST_ARCHTYPE addend;
727 int offset;
728 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000729};
Eric Andersencffd5022002-05-24 06:50:15 +0000730
Eric Andersen21adca72000-12-06 18:18:26 +0000731#endif
732
Eric Andersencffd5022002-05-24 06:50:15 +0000733#if defined(CONFIG_USE_SINGLE)
734
735struct arch_single_entry
736{
Eric Andersen9f16d612000-06-12 23:11:16 +0000737 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000738 int inited : 1;
739 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000740};
Eric Andersencffd5022002-05-24 06:50:15 +0000741
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000742#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000743
Eric Andersen2bf658d2001-02-24 20:01:53 +0000744#if defined(__mips__)
745struct mips_hi16
746{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000747 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000748 ElfW(Addr) *addr;
749 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000750};
751#endif
752
Eric Andersenfe4208f2000-09-24 03:44:29 +0000753struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000755#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000756 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000757#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000758#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000759 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000760#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000761#if defined(__mips__)
762 struct mips_hi16 *mips_hi16_list;
763#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000764};
765
Eric Andersenfe4208f2000-09-24 03:44:29 +0000766struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000767 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000768#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000769#if defined(CONFIG_USE_PLT_LIST)
770 struct arch_list_entry *pltent;
771#else
772 struct arch_single_entry pltent;
773#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000774#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000775#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000776 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000777#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000778};
779
780
Eric Andersen9f16d612000-06-12 23:11:16 +0000781struct external_module {
782 const char *name;
783 ElfW(Addr) addr;
784 int used;
785 size_t nsyms;
786 struct new_module_symbol *syms;
787};
788
Eric Andersen044228d2001-07-17 01:12:36 +0000789static struct new_module_symbol *ksyms;
790static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000791
Eric Andersen044228d2001-07-17 01:12:36 +0000792static struct external_module *ext_modules;
793static int n_ext_modules;
794static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000795extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000796
Eric Andersen61f83052002-06-22 17:15:42 +0000797static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000798static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000799
Eric Andersenfe4208f2000-09-24 03:44:29 +0000800
Erik Andersen02104321999-12-17 18:57:34 +0000801
Eric Andersen9f16d612000-06-12 23:11:16 +0000802/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000803
Eric Andersen9f16d612000-06-12 23:11:16 +0000804
Eric Andersen14d35432001-05-14 17:07:32 +0000805static int check_module_name_match(const char *filename, struct stat *statbuf,
806 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000807{
Eric Andersen14d35432001-05-14 17:07:32 +0000808 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000809
Eric Andersen14d35432001-05-14 17:07:32 +0000810 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000811 return (FALSE);
812 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000813 char *tmp, *tmp1 = bb_xstrdup(filename);
814 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000815 if (strcmp(tmp, fullname) == 0) {
816 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000817 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000818 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000819 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000820 }
Eric Andersen14d35432001-05-14 17:07:32 +0000821 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000822 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000823 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000824}
825
Erik Andersen02104321999-12-17 18:57:34 +0000826
Eric Andersen9f16d612000-06-12 23:11:16 +0000827/*======================================================================*/
828
Eric Andersen044228d2001-07-17 01:12:36 +0000829static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000830{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000831 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833
Eric Andersencffd5022002-05-24 06:50:15 +0000834 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000835
Eric Andersen9f16d612000-06-12 23:11:16 +0000836 return &f->root;
837}
838
Eric Andersen044228d2001-07-17 01:12:36 +0000839static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000840{
841 return xmalloc(sizeof(struct obj_section));
842}
843
Eric Andersen044228d2001-07-17 01:12:36 +0000844static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000845{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000846 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000847 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000848
Eric Andersencffd5022002-05-24 06:50:15 +0000849 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000850
Eric Andersen9f16d612000-06-12 23:11:16 +0000851 return &sym->root;
852}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000853
Eric Andersen044228d2001-07-17 01:12:36 +0000854static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000855arch_apply_relocation(struct obj_file *f,
856 struct obj_section *targsec,
857 struct obj_section *symsec,
858 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000859 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000860{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000861 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000862 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000863 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
864 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000865#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
866 struct arch_symbol *isym = (struct arch_symbol *) sym;
867#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000868#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000869#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000870 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000871#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000872#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000873#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000874 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000875 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000876# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000877 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000878# else
Eric Andersencffd5022002-05-24 06:50:15 +0000879 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000880# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000881#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000882
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000883 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000884
Eric Andersencffd5022002-05-24 06:50:15 +0000885#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_NONE:
888 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000889
Eric Andersen3b1a7442003-12-24 20:30:45 +0000890 case R_ARM_ABS32:
891 *loc += v;
892 break;
Miles Baderae28b042002-04-01 09:34:25 +0000893
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 case R_ARM_GOT32:
895 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000896
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000898 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
899 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000901
Eric Andersen3496fdc2006-01-30 23:09:20 +0000902 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000903 *loc += got - dot;
904 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000905
Eric Andersen3b1a7442003-12-24 20:30:45 +0000906 case R_ARM_PC24:
907 case R_ARM_PLT32:
908 goto bb_use_plt;
909
910 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3496fdc2006-01-30 23:09:20 +0000911 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 *loc += v - got;
913 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000914
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915#elif defined(__cris__)
916
917 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000918 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000919
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000920 case R_CRIS_32:
921 /* CRIS keeps the relocation value in the r_addend field and
922 * should not use whats in *loc at all
923 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000924 *loc = v;
925 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000926
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000927#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000928
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000929 case R_H8_DIR24R8:
930 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
931 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000932 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000933 case R_H8_DIR24A8:
934 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000935 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000936 case R_H8_DIR32:
937 case R_H8_DIR32A16:
938 *loc += v;
939 break;
940 case R_H8_PCREL16:
941 v -= dot + 2;
942 if ((ElfW(Sword))v > 0x7fff ||
943 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
944 ret = obj_reloc_overflow;
945 else
946 *(unsigned short *)loc = v;
947 break;
948 case R_H8_PCREL8:
949 v -= dot + 1;
950 if ((ElfW(Sword))v > 0x7f ||
951 (ElfW(Sword))v < -(ElfW(Sword))0x80)
952 ret = obj_reloc_overflow;
953 else
954 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000956
Eric Andersencffd5022002-05-24 06:50:15 +0000957#elif defined(__i386__)
958
Eric Andersen3b1a7442003-12-24 20:30:45 +0000959 case R_386_NONE:
960 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000961
Eric Andersen3b1a7442003-12-24 20:30:45 +0000962 case R_386_32:
963 *loc += v;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_PLT32:
967 case R_386_PC32:
968 *loc += v - dot;
969 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000970
Eric Andersen3b1a7442003-12-24 20:30:45 +0000971 case R_386_GLOB_DAT:
972 case R_386_JMP_SLOT:
973 *loc = v;
974 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000975
Eric Andersen3b1a7442003-12-24 20:30:45 +0000976 case R_386_RELATIVE:
977 *loc += f->baseaddr;
978 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000979
Eric Andersen3b1a7442003-12-24 20:30:45 +0000980 case R_386_GOTPC:
981 assert(got != 0);
982 *loc += got - dot;
983 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000984
Eric Andersen3b1a7442003-12-24 20:30:45 +0000985 case R_386_GOT32:
986 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000987
Eric Andersen3b1a7442003-12-24 20:30:45 +0000988 case R_386_GOTOFF:
989 assert(got != 0);
990 *loc += v - got;
991 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000992
993#elif defined(__mc68000__)
994
Eric Andersen3b1a7442003-12-24 20:30:45 +0000995 case R_68K_NONE:
996 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000997
Eric Andersen3b1a7442003-12-24 20:30:45 +0000998 case R_68K_32:
999 *loc += v;
1000 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001001
Eric Andersen3b1a7442003-12-24 20:30:45 +00001002 case R_68K_8:
1003 if (v > 0xff) {
1004 ret = obj_reloc_overflow;
1005 }
1006 *(char *)loc = v;
1007 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001008
Eric Andersen3b1a7442003-12-24 20:30:45 +00001009 case R_68K_16:
1010 if (v > 0xffff) {
1011 ret = obj_reloc_overflow;
1012 }
1013 *(short *)loc = v;
1014 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001015
Eric Andersen3b1a7442003-12-24 20:30:45 +00001016 case R_68K_PC8:
1017 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001018 if ((ElfW(Sword))v > 0x7f ||
1019 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001020 ret = obj_reloc_overflow;
1021 }
1022 *(char *)loc = v;
1023 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001024
Eric Andersen3b1a7442003-12-24 20:30:45 +00001025 case R_68K_PC16:
1026 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001027 if ((ElfW(Sword))v > 0x7fff ||
1028 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001029 ret = obj_reloc_overflow;
1030 }
1031 *(short *)loc = v;
1032 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001033
Eric Andersen3b1a7442003-12-24 20:30:45 +00001034 case R_68K_PC32:
1035 *(int *)loc = v - dot;
1036 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001037
Eric Andersen3b1a7442003-12-24 20:30:45 +00001038 case R_68K_GLOB_DAT:
1039 case R_68K_JMP_SLOT:
1040 *loc = v;
1041 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001042
Eric Andersen3b1a7442003-12-24 20:30:45 +00001043 case R_68K_RELATIVE:
1044 *(int *)loc += f->baseaddr;
1045 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001046
Eric Andersen3b1a7442003-12-24 20:30:45 +00001047 case R_68K_GOT32:
1048 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001049
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001050# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001051 case R_68K_GOTOFF:
1052 assert(got != 0);
1053 *loc += v - got;
1054 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001055# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001056
1057#elif defined(__mips__)
1058
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 case R_MIPS_NONE:
1060 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001061
Eric Andersen3b1a7442003-12-24 20:30:45 +00001062 case R_MIPS_32:
1063 *loc += v;
1064 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001065
Eric Andersen3b1a7442003-12-24 20:30:45 +00001066 case R_MIPS_26:
1067 if (v % 4)
1068 ret = obj_reloc_dangerous;
1069 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1070 ret = obj_reloc_overflow;
1071 *loc =
1072 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1073 0x03ffffff);
1074 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001075
Eric Andersen3b1a7442003-12-24 20:30:45 +00001076 case R_MIPS_HI16:
1077 {
1078 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001079
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080 /* We cannot relocate this one now because we don't know the value
1081 of the carry we need to add. Save the information, and let LO16
1082 do the actual relocation. */
1083 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1084 n->addr = loc;
1085 n->value = v;
1086 n->next = ifile->mips_hi16_list;
1087 ifile->mips_hi16_list = n;
1088 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001089 }
1090
Eric Andersen3b1a7442003-12-24 20:30:45 +00001091 case R_MIPS_LO16:
1092 {
1093 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001094 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095
1096 /* Sign extend the addend we extract from the lo insn. */
1097 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1098
1099 if (ifile->mips_hi16_list != NULL) {
1100 struct mips_hi16 *l;
1101
1102 l = ifile->mips_hi16_list;
1103 while (l != NULL) {
1104 struct mips_hi16 *next;
1105 unsigned long insn;
1106
1107 /* The value for the HI16 had best be the same. */
1108 assert(v == l->value);
1109
1110 /* Do the HI16 relocation. Note that we actually don't
1111 need to know anything about the LO16 itself, except where
1112 to find the low 16 bits of the addend needed by the LO16. */
1113 insn = *l->addr;
1114 val =
1115 ((insn & 0xffff) << 16) +
1116 vallo;
1117 val += v;
1118
1119 /* Account for the sign extension that will happen in the
1120 low bits. */
1121 val =
1122 ((val >> 16) +
1123 ((val & 0x8000) !=
1124 0)) & 0xffff;
1125
1126 insn = (insn & ~0xffff) | val;
1127 *l->addr = insn;
1128
1129 next = l->next;
1130 free(l);
1131 l = next;
1132 }
1133
1134 ifile->mips_hi16_list = NULL;
1135 }
1136
1137 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1138 val = v + vallo;
1139 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1140 *loc = insnlo;
1141 break;
1142 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001143
Mike Frysingerf982d862006-01-04 00:11:26 +00001144#elif defined(__nios2__)
1145
1146 case R_NIOS2_NONE:
1147 break;
1148
1149 case R_NIOS2_BFD_RELOC_32:
1150 *loc += v;
1151 break;
1152
1153 case R_NIOS2_BFD_RELOC_16:
1154 if (v > 0xffff) {
1155 ret = obj_reloc_overflow;
1156 }
1157 *(short *)loc = v;
1158 break;
1159
1160 case R_NIOS2_BFD_RELOC_8:
1161 if (v > 0xff) {
1162 ret = obj_reloc_overflow;
1163 }
1164 *(char *)loc = v;
1165 break;
1166
1167 case R_NIOS2_S16:
1168 {
1169 Elf32_Addr word;
1170
1171 if ((Elf32_Sword)v > 0x7fff ||
1172 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1173 ret = obj_reloc_overflow;
1174 }
1175
1176 word = *loc;
1177 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1178 (word & 0x3f);
1179 }
1180 break;
1181
1182 case R_NIOS2_U16:
1183 {
1184 Elf32_Addr word;
1185
1186 if (v > 0xffff) {
1187 ret = obj_reloc_overflow;
1188 }
1189
1190 word = *loc;
1191 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1192 (word & 0x3f);
1193 }
1194 break;
1195
1196 case R_NIOS2_PCREL16:
1197 {
1198 Elf32_Addr word;
1199
1200 v -= dot + 4;
1201 if ((Elf32_Sword)v > 0x7fff ||
1202 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1203 ret = obj_reloc_overflow;
1204 }
1205
1206 word = *loc;
1207 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1208 }
1209 break;
1210
1211 case R_NIOS2_GPREL:
1212 {
1213 Elf32_Addr word, gp;
1214 /* get _gp */
1215 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1216 v-=gp;
1217 if ((Elf32_Sword)v > 0x7fff ||
1218 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1219 ret = obj_reloc_overflow;
1220 }
1221
1222 word = *loc;
1223 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1224 }
1225 break;
1226
1227 case R_NIOS2_CALL26:
1228 if (v & 3)
1229 ret = obj_reloc_dangerous;
1230 if ((v >> 28) != (dot >> 28))
1231 ret = obj_reloc_overflow;
1232 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1233 break;
1234
1235 case R_NIOS2_IMM5:
1236 {
1237 Elf32_Addr word;
1238
1239 if (v > 0x1f) {
1240 ret = obj_reloc_overflow;
1241 }
1242
1243 word = *loc & ~0x7c0;
1244 *loc = word | ((v & 0x1f) << 6);
1245 }
1246 break;
1247
1248 case R_NIOS2_IMM6:
1249 {
1250 Elf32_Addr word;
1251
1252 if (v > 0x3f) {
1253 ret = obj_reloc_overflow;
1254 }
1255
1256 word = *loc & ~0xfc0;
1257 *loc = word | ((v & 0x3f) << 6);
1258 }
1259 break;
1260
1261 case R_NIOS2_IMM8:
1262 {
1263 Elf32_Addr word;
1264
1265 if (v > 0xff) {
1266 ret = obj_reloc_overflow;
1267 }
1268
1269 word = *loc & ~0x3fc0;
1270 *loc = word | ((v & 0xff) << 6);
1271 }
1272 break;
1273
1274 case R_NIOS2_HI16:
1275 {
1276 Elf32_Addr word;
1277
1278 word = *loc;
1279 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1280 (word & 0x3f);
1281 }
1282 break;
1283
1284 case R_NIOS2_LO16:
1285 {
1286 Elf32_Addr word;
1287
1288 word = *loc;
1289 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1290 (word & 0x3f);
1291 }
1292 break;
1293
1294 case R_NIOS2_HIADJ16:
1295 {
1296 Elf32_Addr word1, word2;
1297
1298 word1 = *loc;
1299 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1300 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1301 (word1 & 0x3f);
1302 }
1303 break;
1304
Mike Frysingerebee0e72006-02-18 06:14:31 +00001305#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001306 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001307
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001308#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001309
Eric Andersen3b1a7442003-12-24 20:30:45 +00001310 case R_PPC_ADDR16_HA:
1311 *(unsigned short *)loc = (v + 0x8000) >> 16;
1312 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001313
Eric Andersen3b1a7442003-12-24 20:30:45 +00001314 case R_PPC_ADDR16_HI:
1315 *(unsigned short *)loc = v >> 16;
1316 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001317
Eric Andersen3b1a7442003-12-24 20:30:45 +00001318 case R_PPC_ADDR16_LO:
1319 *(unsigned short *)loc = v;
1320 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001321
Eric Andersen3b1a7442003-12-24 20:30:45 +00001322 case R_PPC_REL24:
1323 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001324
Eric Andersen3b1a7442003-12-24 20:30:45 +00001325 case R_PPC_REL32:
1326 *loc = v - dot;
1327 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001328
Eric Andersen3b1a7442003-12-24 20:30:45 +00001329 case R_PPC_ADDR32:
1330 *loc = v;
1331 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001332
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001333#elif defined(__s390__)
1334
1335 case R_390_32:
1336 *(unsigned int *) loc += v;
1337 break;
1338 case R_390_16:
1339 *(unsigned short *) loc += v;
1340 break;
1341 case R_390_8:
1342 *(unsigned char *) loc += v;
1343 break;
1344
1345 case R_390_PC32:
1346 *(unsigned int *) loc += v - dot;
1347 break;
1348 case R_390_PC16DBL:
1349 *(unsigned short *) loc += (v - dot) >> 1;
1350 break;
1351 case R_390_PC16:
1352 *(unsigned short *) loc += v - dot;
1353 break;
1354
1355 case R_390_PLT32:
1356 case R_390_PLT16DBL:
1357 /* find the plt entry and initialize it. */
1358 assert(isym != NULL);
1359 pe = (struct arch_single_entry *) &isym->pltent;
1360 assert(pe->allocated);
1361 if (pe->inited == 0) {
1362 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1363 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1364 ip[1] = 0x100607f1;
1365 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1366 ip[2] = v - 2;
1367 else
1368 ip[2] = v;
1369 pe->inited = 1;
1370 }
1371
1372 /* Insert relative distance to target. */
1373 v = plt + pe->offset - dot;
1374 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1375 *(unsigned int *) loc = (unsigned int) v;
1376 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1377 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1378 break;
1379
1380 case R_390_GLOB_DAT:
1381 case R_390_JMP_SLOT:
1382 *loc = v;
1383 break;
1384
1385 case R_390_RELATIVE:
1386 *loc += f->baseaddr;
1387 break;
1388
1389 case R_390_GOTPC:
1390 assert(got != 0);
1391 *(unsigned long *) loc += got - dot;
1392 break;
1393
1394 case R_390_GOT12:
1395 case R_390_GOT16:
1396 case R_390_GOT32:
1397 assert(isym != NULL);
1398 assert(got != 0);
1399 if (!isym->gotent.inited)
1400 {
1401 isym->gotent.inited = 1;
1402 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1403 }
1404 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1405 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1406 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1407 *(unsigned short *) loc += isym->gotent.offset;
1408 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1409 *(unsigned int *) loc += isym->gotent.offset;
1410 break;
1411
1412# ifndef R_390_GOTOFF32
1413# define R_390_GOTOFF32 R_390_GOTOFF
1414# endif
1415 case R_390_GOTOFF32:
1416 assert(got != 0);
1417 *loc += v - got;
1418 break;
1419
Eric Andersencffd5022002-05-24 06:50:15 +00001420#elif defined(__sh__)
1421
Eric Andersen3b1a7442003-12-24 20:30:45 +00001422 case R_SH_NONE:
1423 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001424
Eric Andersen3b1a7442003-12-24 20:30:45 +00001425 case R_SH_DIR32:
1426 *loc += v;
1427 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001428
Eric Andersen3b1a7442003-12-24 20:30:45 +00001429 case R_SH_REL32:
1430 *loc += v - dot;
1431 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001432
Eric Andersen3b1a7442003-12-24 20:30:45 +00001433 case R_SH_PLT32:
1434 *loc = v - dot;
1435 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001436
Eric Andersen3b1a7442003-12-24 20:30:45 +00001437 case R_SH_GLOB_DAT:
1438 case R_SH_JMP_SLOT:
1439 *loc = v;
1440 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001441
Eric Andersen3b1a7442003-12-24 20:30:45 +00001442 case R_SH_RELATIVE:
1443 *loc = f->baseaddr + rel->r_addend;
1444 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001445
Eric Andersen3b1a7442003-12-24 20:30:45 +00001446 case R_SH_GOTPC:
1447 assert(got != 0);
1448 *loc = got - dot + rel->r_addend;
1449 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001450
Eric Andersen3b1a7442003-12-24 20:30:45 +00001451 case R_SH_GOT32:
1452 goto bb_use_got;
1453
1454 case R_SH_GOTOFF:
1455 assert(got != 0);
1456 *loc = v - got;
1457 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001458
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001459# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001460 case R_SH_IMM_MEDLOW16:
1461 case R_SH_IMM_LOW16:
1462 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001463 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001464
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001465 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001467
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 /*
1469 * movi and shori have the format:
1470 *
1471 * | op | imm | reg | reserved |
1472 * 31..26 25..10 9.. 4 3 .. 0
1473 *
1474 * so we simply mask and or in imm.
1475 */
1476 word = *loc & ~0x3fffc00;
1477 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001480
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 break;
1482 }
Eric Andersenbf833552003-08-13 19:56:33 +00001483
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 case R_SH_IMM_MEDLOW16_PCREL:
1485 case R_SH_IMM_LOW16_PCREL:
1486 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001487 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001488
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001490
Eric Andersen3b1a7442003-12-24 20:30:45 +00001491 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001492
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001493 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001494 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001495
Eric Andersen3b1a7442003-12-24 20:30:45 +00001496 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001497
Eric Andersen3b1a7442003-12-24 20:30:45 +00001498 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001499
Eric Andersen3b1a7442003-12-24 20:30:45 +00001500 break;
1501 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001502# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001503
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001504#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001505
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 case R_V850_NONE:
1507 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001508
Eric Andersen3b1a7442003-12-24 20:30:45 +00001509 case R_V850_32:
1510 /* We write two shorts instead of a long because even
1511 32-bit insns only need half-word alignment, but
1512 32-bit data needs to be long-word aligned. */
1513 v += ((unsigned short *)loc)[0];
1514 v += ((unsigned short *)loc)[1] << 16;
1515 ((unsigned short *)loc)[0] = v & 0xffff;
1516 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1517 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001518
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 case R_V850_22_PCREL:
1520 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001521
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001522#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001523
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001524 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001526
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001527 case R_X86_64_64:
1528 *loc += v;
1529 break;
1530
1531 case R_X86_64_32:
1532 *(unsigned int *) loc += v;
1533 if (v > 0xffffffff)
1534 {
1535 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1536 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1537 }
1538 break;
1539
1540 case R_X86_64_32S:
1541 *(signed int *) loc += v;
1542 break;
1543
1544 case R_X86_64_16:
1545 *(unsigned short *) loc += v;
1546 break;
1547
1548 case R_X86_64_8:
1549 *(unsigned char *) loc += v;
1550 break;
1551
1552 case R_X86_64_PC32:
1553 *(unsigned int *) loc += v - dot;
1554 break;
1555
1556 case R_X86_64_PC16:
1557 *(unsigned short *) loc += v - dot;
1558 break;
1559
1560 case R_X86_64_PC8:
1561 *(unsigned char *) loc += v - dot;
1562 break;
1563
1564 case R_X86_64_GLOB_DAT:
1565 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001566 *loc = v;
1567 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001568
1569 case R_X86_64_RELATIVE:
1570 *loc += f->baseaddr;
1571 break;
1572
1573 case R_X86_64_GOT32:
1574 case R_X86_64_GOTPCREL:
1575 goto bb_use_got;
1576# if 0
1577 assert(isym != NULL);
1578 if (!isym->gotent.reloc_done)
1579 {
1580 isym->gotent.reloc_done = 1;
1581 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1582 }
1583 /* XXX are these really correct? */
1584 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1585 *(unsigned int *) loc += v + isym->gotent.offset;
1586 else
1587 *loc += isym->gotent.offset;
1588 break;
1589# endif
1590
Mike Frysingerf982d862006-01-04 00:11:26 +00001591#else
1592# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001593#endif
1594
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001595 default:
1596 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1597 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001598 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001599
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001600#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001601
Eric Andersen3b1a7442003-12-24 20:30:45 +00001602bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001603
Eric Andersen3b1a7442003-12-24 20:30:45 +00001604 /* find the plt entry and initialize it if necessary */
1605 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001606
Eric Andersencffd5022002-05-24 06:50:15 +00001607#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001608 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1609 pe = pe->next;
1610 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001611#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001612 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001613#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001614
Eric Andersen3b1a7442003-12-24 20:30:45 +00001615 if (! pe->inited) {
1616 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001617
Eric Andersen3b1a7442003-12-24 20:30:45 +00001618 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001619
1620#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001621 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1622 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001623#endif
1624#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001625 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001626 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001627 ip[2] = 0x7d6903a6; /* mtctr r11 */
1628 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001629#endif
Miles Baderae28b042002-04-01 09:34:25 +00001630#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001631 /* We have to trash a register, so we assume that any control
1632 transfer more than 21-bits away must be a function call
1633 (so we can use a call-clobbered register). */
1634 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1635 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001636#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001637 pe->inited = 1;
1638 }
Eric Andersen21adca72000-12-06 18:18:26 +00001639
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 /* relative distance to target */
1641 v -= dot;
1642 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001643#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001644 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001645#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001646 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001647#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 /* go via the plt */
1649 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001650
1651#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001653#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001655#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001656 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001657
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001659#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001660 /* Convert to words. */
1661 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001662
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001664#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001665#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001666 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001667#endif
Miles Baderae28b042002-04-01 09:34:25 +00001668#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 /* We write two shorts instead of a long because even 32-bit insns
1670 only need half-word alignment, but the 32-bit data write needs
1671 to be long-word aligned. */
1672 ((unsigned short *)loc)[0] =
1673 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1674 | ((v >> 16) & 0x3f); /* offs high part */
1675 ((unsigned short *)loc)[1] =
1676 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001677#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001679#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001680
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001681#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001683
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 assert(isym != NULL);
1685 /* needs an entry in the .got: set it, once */
1686 if (!isym->gotent.inited) {
1687 isym->gotent.inited = 1;
1688 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1689 }
1690 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001691#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001692 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001693#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001695#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001696 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001697
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001698#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001699 }
1700
1701 return ret;
1702}
1703
Eric Andersencffd5022002-05-24 06:50:15 +00001704
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001705#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001706
1707static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1708 int offset, int size)
1709{
1710 struct arch_list_entry *pe;
1711
1712 for (pe = *list; pe != NULL; pe = pe->next) {
1713 if (pe->addend == rel->r_addend) {
1714 break;
1715 }
1716 }
1717
1718 if (pe == NULL) {
1719 pe = xmalloc(sizeof(struct arch_list_entry));
1720 pe->next = *list;
1721 pe->addend = rel->r_addend;
1722 pe->offset = offset;
1723 pe->inited = 0;
1724 *list = pe;
1725 return size;
1726 }
1727 return 0;
1728}
1729
1730#endif
1731
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001732#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001733
1734static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1735 int offset, int size)
1736{
1737 if (single->allocated == 0) {
1738 single->allocated = 1;
1739 single->offset = offset;
1740 single->inited = 0;
1741 return size;
1742 }
1743 return 0;
1744}
1745
1746#endif
1747
1748#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1749
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001750static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001751 int offset, int size)
1752{
1753 struct obj_section *myrelsec = obj_find_section(f, name);
1754
1755 if (offset == 0) {
1756 offset += size;
1757 }
1758
1759 if (myrelsec) {
1760 obj_extend_section(myrelsec, offset);
1761 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001762 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001763 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001764 assert(myrelsec);
1765 }
1766
1767 return myrelsec;
1768}
1769
1770#endif
1771
1772static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001773{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001774#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001775 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001776 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001777#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001778 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001779#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001780#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001781 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001782#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001783 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001784 ElfW(RelM) *rel, *relend;
1785 ElfW(Sym) *symtab, *extsym;
1786 const char *strtab, *name;
1787 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001788
Eric Andersen21adca72000-12-06 18:18:26 +00001789 for (i = 0; i < f->header.e_shnum; ++i) {
1790 relsec = f->sections[i];
1791 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001792 continue;
1793
Eric Andersen21adca72000-12-06 18:18:26 +00001794 symsec = f->sections[relsec->header.sh_link];
1795 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001796
Eric Andersen21adca72000-12-06 18:18:26 +00001797 rel = (ElfW(RelM) *) relsec->contents;
1798 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1799 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001800 strtab = (const char *) strsec->contents;
1801
1802 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001803 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001804
Eric Andersencffd5022002-05-24 06:50:15 +00001805#if defined(CONFIG_USE_GOT_ENTRIES)
1806 got_allocate = 0;
1807#endif
1808#if defined(CONFIG_USE_PLT_ENTRIES)
1809 plt_allocate = 0;
1810#endif
1811
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001812 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001813#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001814 case R_ARM_PC24:
1815 case R_ARM_PLT32:
1816 plt_allocate = 1;
1817 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001818
Eric Andersen3b1a7442003-12-24 20:30:45 +00001819 case R_ARM_GOTOFF:
1820 case R_ARM_GOTPC:
1821 got_needed = 1;
1822 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001823
Eric Andersen3b1a7442003-12-24 20:30:45 +00001824 case R_ARM_GOT32:
1825 got_allocate = 1;
1826 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001827
Eric Andersen21adca72000-12-06 18:18:26 +00001828#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001829 case R_386_GOTPC:
1830 case R_386_GOTOFF:
1831 got_needed = 1;
1832 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001833
Eric Andersen3b1a7442003-12-24 20:30:45 +00001834 case R_386_GOT32:
1835 got_allocate = 1;
1836 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001837
1838#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001839 case R_PPC_REL24:
1840 plt_allocate = 1;
1841 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001842
1843#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001844 case R_68K_GOT32:
1845 got_allocate = 1;
1846 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001847
Eric Andersen16451a02004-03-19 12:16:18 +00001848#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001849 case R_68K_GOTOFF:
1850 got_needed = 1;
1851 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001852#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001853
1854#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001855 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001856 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001857 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001858
Eric Andersen3b1a7442003-12-24 20:30:45 +00001859 case R_SH_GOTPC:
1860 case R_SH_GOTOFF:
1861 got_needed = 1;
1862 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001863
1864#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001865 case R_V850_22_PCREL:
1866 plt_needed = 1;
1867 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001868
1869#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001870 default:
1871 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001872 }
1873
Eric Andersen21adca72000-12-06 18:18:26 +00001874 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001875 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001876 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001877 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001878 }
1879 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001880#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001881 if (got_allocate) {
1882 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001883 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001884 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001885
1886 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001887 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001888#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001889#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001890 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001891#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001892 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001893 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001894 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001895#else
1896 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001897 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001898 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001899#endif
1900 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001901 }
1902#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001903 }
Miles Baderae28b042002-04-01 09:34:25 +00001904 }
Eric Andersen21adca72000-12-06 18:18:26 +00001905
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001906#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001907 if (got_needed) {
1908 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001909 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001910 }
Eric Andersen21adca72000-12-06 18:18:26 +00001911#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001912
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001913#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001914 if (plt_needed) {
1915 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001916 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001917 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001918#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001919
1920#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001921}
1922
Eric Andersen9f16d612000-06-12 23:11:16 +00001923/*======================================================================*/
1924
1925/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001926static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001927{
1928 unsigned long h = 0;
1929 unsigned long g;
1930 unsigned char ch;
1931
1932 while (n > 0) {
1933 ch = *name++;
1934 h = (h << 4) + ch;
1935 if ((g = (h & 0xf0000000)) != 0) {
1936 h ^= g >> 24;
1937 h &= ~g;
1938 }
1939 n--;
1940 }
1941 return h;
1942}
1943
Eric Andersen044228d2001-07-17 01:12:36 +00001944static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001945{
1946 return obj_elf_hash_n(name, strlen(name));
1947}
1948
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001949#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001950/* String comparison for non-co-versioned kernel and module. */
1951
1952static int ncv_strcmp(const char *a, const char *b)
1953{
1954 size_t alen = strlen(a), blen = strlen(b);
1955
1956 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1957 return strncmp(a, b, alen);
1958 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1959 return strncmp(a, b, blen);
1960 else
1961 return strcmp(a, b);
1962}
1963
1964/* String hashing for non-co-versioned kernel and module. Here
1965 we are simply forced to drop the crc from the hash. */
1966
1967static unsigned long ncv_symbol_hash(const char *str)
1968{
1969 size_t len = strlen(str);
1970 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1971 len -= 10;
1972 return obj_elf_hash_n(str, len);
1973}
1974
Eric Andersen044228d2001-07-17 01:12:36 +00001975static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001976obj_set_symbol_compare(struct obj_file *f,
1977 int (*cmp) (const char *, const char *),
1978 unsigned long (*hash) (const char *))
1979{
1980 if (cmp)
1981 f->symbol_cmp = cmp;
1982 if (hash) {
1983 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1984 int i;
1985
1986 f->symbol_hash = hash;
1987
1988 memcpy(tmptab, f->symtab, sizeof(tmptab));
1989 memset(f->symtab, 0, sizeof(f->symtab));
1990
1991 for (i = 0; i < HASH_BUCKETS; ++i)
1992 for (sym = tmptab[i]; sym; sym = next) {
1993 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1994 next = sym->next;
1995 sym->next = f->symtab[h];
1996 f->symtab[h] = sym;
1997 }
1998 }
1999}
2000
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002001#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002002
Eric Andersen044228d2001-07-17 01:12:36 +00002003static struct obj_symbol *
2004obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00002005 unsigned long symidx, int info,
2006 int secidx, ElfW(Addr) value,
2007 unsigned long size)
2008{
2009 struct obj_symbol *sym;
2010 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002011 int n_type = ELF_ST_TYPE(info);
2012 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002013
2014 for (sym = f->symtab[hash]; sym; sym = sym->next)
2015 if (f->symbol_cmp(sym->name, name) == 0) {
2016 int o_secidx = sym->secidx;
2017 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002018 int o_type = ELF_ST_TYPE(o_info);
2019 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002020
2021 /* A redefinition! Is it legal? */
2022
2023 if (secidx == SHN_UNDEF)
2024 return sym;
2025 else if (o_secidx == SHN_UNDEF)
2026 goto found;
2027 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2028 /* Cope with local and global symbols of the same name
2029 in the same object file, as might have been created
2030 by ld -r. The only reason locals are now seen at this
2031 level at all is so that we can do semi-sensible things
2032 with parameters. */
2033
2034 struct obj_symbol *nsym, **p;
2035
2036 nsym = arch_new_symbol();
2037 nsym->next = sym->next;
2038 nsym->ksymidx = -1;
2039
2040 /* Excise the old (local) symbol from the hash chain. */
2041 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2042 continue;
2043 *p = sym = nsym;
2044 goto found;
2045 } else if (n_binding == STB_LOCAL) {
2046 /* Another symbol of the same name has already been defined.
2047 Just add this to the local table. */
2048 sym = arch_new_symbol();
2049 sym->next = NULL;
2050 sym->ksymidx = -1;
2051 f->local_symtab[symidx] = sym;
2052 goto found;
2053 } else if (n_binding == STB_WEAK)
2054 return sym;
2055 else if (o_binding == STB_WEAK)
2056 goto found;
2057 /* Don't unify COMMON symbols with object types the programmer
2058 doesn't expect. */
2059 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002060 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002061 return sym;
2062 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002063 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002064 goto found;
2065 else {
2066 /* Don't report an error if the symbol is coming from
2067 the kernel or some external module. */
2068 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002069 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002070 return sym;
2071 }
2072 }
2073
2074 /* Completely new symbol. */
2075 sym = arch_new_symbol();
2076 sym->next = f->symtab[hash];
2077 f->symtab[hash] = sym;
2078 sym->ksymidx = -1;
2079
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002080 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002081 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002082 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002083 name, (long) symidx, (long) f->local_symtab_size);
2084 else
2085 f->local_symtab[symidx] = sym;
2086 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002087
Eric Andersen3b1a7442003-12-24 20:30:45 +00002088found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002089 sym->name = name;
2090 sym->value = value;
2091 sym->size = size;
2092 sym->secidx = secidx;
2093 sym->info = info;
2094
2095 return sym;
2096}
2097
Eric Andersen044228d2001-07-17 01:12:36 +00002098static struct obj_symbol *
2099obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002100{
2101 struct obj_symbol *sym;
2102 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2103
2104 for (sym = f->symtab[hash]; sym; sym = sym->next)
2105 if (f->symbol_cmp(sym->name, name) == 0)
2106 return sym;
2107
2108 return NULL;
2109}
2110
Eric Andersen044228d2001-07-17 01:12:36 +00002111static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002112 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2113{
2114 if (sym) {
2115 if (sym->secidx >= SHN_LORESERVE)
2116 return sym->value;
2117
2118 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2119 } else {
2120 /* As a special case, a NULL sym has value zero. */
2121 return 0;
2122 }
2123}
2124
Eric Andersen044228d2001-07-17 01:12:36 +00002125static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002126{
2127 int i, n = f->header.e_shnum;
2128
2129 for (i = 0; i < n; ++i)
2130 if (strcmp(f->sections[i]->name, name) == 0)
2131 return f->sections[i];
2132
2133 return NULL;
2134}
2135
2136static int obj_load_order_prio(struct obj_section *a)
2137{
2138 unsigned long af, ac;
2139
2140 af = a->header.sh_flags;
2141
2142 ac = 0;
2143 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002144 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002145 ac |= 32;
2146 if (af & SHF_ALLOC)
2147 ac |= 16;
2148 if (!(af & SHF_WRITE))
2149 ac |= 8;
2150 if (af & SHF_EXECINSTR)
2151 ac |= 4;
2152 if (a->header.sh_type != SHT_NOBITS)
2153 ac |= 2;
2154
2155 return ac;
2156}
2157
Eric Andersen044228d2001-07-17 01:12:36 +00002158static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002159obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2160{
2161 struct obj_section **p;
2162 int prio = obj_load_order_prio(sec);
2163 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2164 if (obj_load_order_prio(*p) < prio)
2165 break;
2166 sec->load_next = *p;
2167 *p = sec;
2168}
2169
Eric Andersen044228d2001-07-17 01:12:36 +00002170static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002171 const char *name,
2172 unsigned long align,
2173 unsigned long size)
2174{
2175 int newidx = f->header.e_shnum++;
2176 struct obj_section *sec;
2177
2178 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2179 f->sections[newidx] = sec = arch_new_section();
2180
2181 memset(sec, 0, sizeof(*sec));
2182 sec->header.sh_type = SHT_PROGBITS;
2183 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2184 sec->header.sh_size = size;
2185 sec->header.sh_addralign = align;
2186 sec->name = name;
2187 sec->idx = newidx;
2188 if (size)
2189 sec->contents = xmalloc(size);
2190
2191 obj_insert_section_load_order(f, sec);
2192
2193 return sec;
2194}
2195
Eric Andersen044228d2001-07-17 01:12:36 +00002196static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002197 const char *name,
2198 unsigned long align,
2199 unsigned long size)
2200{
2201 int newidx = f->header.e_shnum++;
2202 struct obj_section *sec;
2203
2204 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2205 f->sections[newidx] = sec = arch_new_section();
2206
2207 memset(sec, 0, sizeof(*sec));
2208 sec->header.sh_type = SHT_PROGBITS;
2209 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2210 sec->header.sh_size = size;
2211 sec->header.sh_addralign = align;
2212 sec->name = name;
2213 sec->idx = newidx;
2214 if (size)
2215 sec->contents = xmalloc(size);
2216
2217 sec->load_next = f->load_order;
2218 f->load_order = sec;
2219 if (f->load_order_search_start == &f->load_order)
2220 f->load_order_search_start = &sec->load_next;
2221
2222 return sec;
2223}
2224
Eric Andersen044228d2001-07-17 01:12:36 +00002225static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002226{
2227 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002228 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002229 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2230 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002231 return sec->contents + oldsize;
2232}
2233
2234
Eric Andersen9f16d612000-06-12 23:11:16 +00002235/* Conditionally add the symbols from the given symbol set to the
2236 new module. */
2237
2238static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002239add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002240 int idx, struct new_module_symbol *syms, size_t nsyms)
2241{
2242 struct new_module_symbol *s;
2243 size_t i;
2244 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002245#ifdef SYMBOL_PREFIX
2246 char *name_buf = 0;
2247 size_t name_alloced_size = 0;
2248#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002249#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2250 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002251
Glenn L McGrath759515c2003-08-30 06:00:33 +00002252 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002253#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002254 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002255 /* Only add symbols that are already marked external.
2256 If we override locals we may cause problems for
2257 argument initialization. We will also create a false
2258 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002259 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002260 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002261
Glenn L McGrath759515c2003-08-30 06:00:33 +00002262 /* GPL licensed modules can use symbols exported with
2263 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2264 * exported names. Non-GPL modules never see any GPLONLY_
2265 * symbols so they cannot fudge it by adding the prefix on
2266 * their references.
2267 */
2268 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002269#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002270 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002271 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002272 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002273#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002274 continue;
2275 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002276 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002277
Miles Baderae28b042002-04-01 09:34:25 +00002278#ifdef SYMBOL_PREFIX
2279 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2280 kernel exports `C names', but module object files
2281 reference `linker names'). */
2282 size_t extra = sizeof SYMBOL_PREFIX;
2283 size_t name_size = strlen (name) + extra;
2284 if (name_size > name_alloced_size) {
2285 name_alloced_size = name_size * 2;
2286 name_buf = alloca (name_alloced_size);
2287 }
2288 strcpy (name_buf, SYMBOL_PREFIX);
2289 strcpy (name_buf + extra - 1, name);
2290 name = name_buf;
2291#endif /* SYMBOL_PREFIX */
2292
2293 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002294 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002295#ifdef SYMBOL_PREFIX
2296 /* Put NAME_BUF into more permanent storage. */
2297 name = xmalloc (name_size);
2298 strcpy (name, name_buf);
2299#endif
2300 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002301 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002302 STT_NOTYPE),
2303 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002304 /* Did our symbol just get installed? If so, mark the
2305 module as "used". */
2306 if (sym->secidx == idx)
2307 used = 1;
2308 }
2309 }
2310
2311 return used;
2312}
2313
2314static void add_kernel_symbols(struct obj_file *f)
2315{
2316 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002317 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002318
2319 /* Add module symbols first. */
2320
2321 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2322 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002323 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2324 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002325
2326 n_ext_modules_used = nused;
2327
2328 /* And finally the symbols from the kernel proper. */
2329
2330 if (nksyms)
2331 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2332}
2333
2334static char *get_modinfo_value(struct obj_file *f, const char *key)
2335{
2336 struct obj_section *sec;
2337 char *p, *v, *n, *ep;
2338 size_t klen = strlen(key);
2339
2340 sec = obj_find_section(f, ".modinfo");
2341 if (sec == NULL)
2342 return NULL;
2343 p = sec->contents;
2344 ep = p + sec->header.sh_size;
2345 while (p < ep) {
2346 v = strchr(p, '=');
2347 n = strchr(p, '\0');
2348 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002349 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002350 return v + 1;
2351 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002352 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002353 return n;
2354 }
2355 p = n + 1;
2356 }
2357
2358 return NULL;
2359}
2360
2361
2362/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002363/* Functions relating to module loading after 2.1.18. */
2364
2365static int
2366new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2367{
2368 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002369 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002370 struct obj_symbol *sym;
2371 char *contents, *loc;
2372 int min, max, n;
2373
2374 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002375 if ((q = strchr(p, '=')) == NULL) {
2376 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002377 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002378 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002379
2380 key = alloca(q - p + 6);
2381 memcpy(key, "parm_", 5);
2382 memcpy(key + 5, p, q - p);
2383 key[q - p + 5] = 0;
2384
2385 p = get_modinfo_value(f, key);
2386 key += 5;
2387 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002388 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002389 return 0;
2390 }
2391
Miles Baderae28b042002-04-01 09:34:25 +00002392#ifdef SYMBOL_PREFIX
2393 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2394 strcpy (sym_name, SYMBOL_PREFIX);
2395 strcat (sym_name, key);
2396#else
2397 sym_name = key;
2398#endif
2399 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002400
2401 /* Also check that the parameter was not resolved from the kernel. */
2402 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002403 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002404 return 0;
2405 }
2406
2407 if (isdigit(*p)) {
2408 min = strtoul(p, &p, 10);
2409 if (*p == '-')
2410 max = strtoul(p + 1, &p, 10);
2411 else
2412 max = min;
2413 } else
2414 min = max = 1;
2415
2416 contents = f->sections[sym->secidx]->contents;
2417 loc = contents + sym->value;
2418 n = (*++q != '\0');
2419
2420 while (1) {
2421 if ((*p == 's') || (*p == 'c')) {
2422 char *str;
2423
2424 /* Do C quoting if we begin with a ", else slurp the lot. */
2425 if (*q == '"') {
2426 char *r;
2427
2428 str = alloca(strlen(q));
2429 for (r = str, q++; *q != '"'; ++q, ++r) {
2430 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002431 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002432 key);
2433 return 0;
2434 } else if (*q == '\\')
2435 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002436 case 'a':
2437 *r = '\a';
2438 break;
2439 case 'b':
2440 *r = '\b';
2441 break;
2442 case 'e':
2443 *r = '\033';
2444 break;
2445 case 'f':
2446 *r = '\f';
2447 break;
2448 case 'n':
2449 *r = '\n';
2450 break;
2451 case 'r':
2452 *r = '\r';
2453 break;
2454 case 't':
2455 *r = '\t';
2456 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002457
Eric Andersen3b1a7442003-12-24 20:30:45 +00002458 case '0':
2459 case '1':
2460 case '2':
2461 case '3':
2462 case '4':
2463 case '5':
2464 case '6':
2465 case '7':
2466 {
2467 int c = *q - '0';
2468 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002469 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002470 if (q[1] >= '0' && q[1] <= '7')
2471 c = (c * 8) + *++q - '0';
2472 }
2473 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002474 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002475 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002476
Eric Andersen3b1a7442003-12-24 20:30:45 +00002477 default:
2478 *r = *q;
2479 break;
2480 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002481 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002482 }
2483 *r = '\0';
2484 ++q;
2485 } else {
2486 char *r;
2487
2488 /* In this case, the string is not quoted. We will break
2489 it using the coma (like for ints). If the user wants to
2490 include comas in a string, he just has to quote it */
2491
2492 /* Search the next coma */
2493 r = strchr(q, ',');
2494
2495 /* Found ? */
2496 if (r != (char *) NULL) {
2497 /* Recopy the current field */
2498 str = alloca(r - q + 1);
2499 memcpy(str, q, r - q);
2500
Eric Andersenaff114c2004-04-14 17:51:38 +00002501 /* I don't know if it is useful, as the previous case
2502 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002503 str[r - q] = '\0';
2504
2505 /* Keep next fields */
2506 q = r;
2507 } else {
2508 /* last string */
2509 str = q;
2510 q = "";
2511 }
2512 }
2513
2514 if (*p == 's') {
2515 /* Normal string */
2516 obj_string_patch(f, sym->secidx, loc - contents, str);
2517 loc += tgt_sizeof_char_p;
2518 } else {
2519 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002520 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002521
2522 /* Get the size of each member */
2523 /* Probably we should do that outside the loop ? */
2524 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002525 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002526 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002527 return 0;
2528 }
2529 charssize = strtoul(p + 1, (char **) NULL, 10);
2530
2531 /* Check length */
2532 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002533 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002534 charssize - 1);
2535 return 0;
2536 }
2537
2538 /* Copy to location */
2539 strcpy((char *) loc, str);
2540 loc += charssize;
2541 }
2542 } else {
2543 long v = strtoul(q, &q, 0);
2544 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002545 case 'b':
2546 *loc++ = v;
2547 break;
2548 case 'h':
2549 *(short *) loc = v;
2550 loc += tgt_sizeof_short;
2551 break;
2552 case 'i':
2553 *(int *) loc = v;
2554 loc += tgt_sizeof_int;
2555 break;
2556 case 'l':
2557 *(long *) loc = v;
2558 loc += tgt_sizeof_long;
2559 break;
2560
2561 default:
2562 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2563 return 0;
2564 }
2565 }
2566
2567retry_end_of_value:
2568 switch (*q) {
2569 case '\0':
2570 goto end_of_arg;
2571
2572 case ' ':
2573 case '\t':
2574 case '\n':
2575 case '\r':
2576 ++q;
2577 goto retry_end_of_value;
2578
2579 case ',':
2580 if (++n > max) {
2581 bb_error_msg("too many values for %s (max %d)", key, max);
2582 return 0;
2583 }
2584 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002585 break;
2586
2587 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002588 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002589 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002590 }
2591 }
2592
Eric Andersen3b1a7442003-12-24 20:30:45 +00002593end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002594 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002595 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002596 return 0;
2597 }
2598
2599 argc--, argv++;
2600 }
2601
2602 return 1;
2603}
2604
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002605#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002606static int new_is_module_checksummed(struct obj_file *f)
2607{
2608 const char *p = get_modinfo_value(f, "using_checksums");
2609 if (p)
2610 return atoi(p);
2611 else
2612 return 0;
2613}
2614
2615/* Get the module's kernel version in the canonical integer form. */
2616
2617static int
2618new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2619{
2620 char *p, *q;
2621 int a, b, c;
2622
2623 p = get_modinfo_value(f, "kernel_version");
2624 if (p == NULL)
2625 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002626 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002627
2628 a = strtoul(p, &p, 10);
2629 if (*p != '.')
2630 return -1;
2631 b = strtoul(p + 1, &p, 10);
2632 if (*p != '.')
2633 return -1;
2634 c = strtoul(p + 1, &q, 10);
2635 if (p + 1 == q)
2636 return -1;
2637
2638 return a << 16 | b << 8 | c;
2639}
2640
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002641#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002642
2643
Eric Andersen9f16d612000-06-12 23:11:16 +00002644/* Fetch the loaded modules, and all currently exported symbols. */
2645
2646static int new_get_kernel_symbols(void)
2647{
2648 char *module_names, *mn;
2649 struct external_module *modules, *m;
2650 struct new_module_symbol *syms, *s;
2651 size_t ret, bufsize, nmod, nsyms, i, j;
2652
2653 /* Collect the loaded modules. */
2654
2655 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002656retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002657 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002658 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002659 module_names = xrealloc(module_names, bufsize = ret);
2660 goto retry_modules_load;
2661 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002662 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002663 return 0;
2664 }
2665
2666 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002667
2668 /* Collect the modules' symbols. */
2669
Mark Whitley94fd4802001-03-12 23:08:34 +00002670 if (nmod){
2671 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2672 memset(modules, 0, nmod * sizeof(*modules));
2673 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002674 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002675 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002676
Mark Whitley94fd4802001-03-12 23:08:34 +00002677 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2678 if (errno == ENOENT) {
2679 /* The module was removed out from underneath us. */
2680 continue;
2681 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002682 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002683 return 0;
2684 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002685
Mark Whitley94fd4802001-03-12 23:08:34 +00002686 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002687retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002688 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2689 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002690 case ENOSPC:
2691 syms = xrealloc(syms, bufsize = ret);
2692 goto retry_mod_sym_load;
2693 case ENOENT:
2694 /* The module was removed out from underneath us. */
2695 continue;
2696 default:
2697 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2698 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002699 }
2700 }
2701 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002702
Mark Whitley94fd4802001-03-12 23:08:34 +00002703 m->name = mn;
2704 m->addr = info.addr;
2705 m->nsyms = nsyms;
2706 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002707
Mark Whitley94fd4802001-03-12 23:08:34 +00002708 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2709 s->name += (unsigned long) syms;
2710 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002711 }
2712 }
2713
2714 /* Collect the kernel's symbols. */
2715
2716 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002717retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002718 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002719 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002720 syms = xrealloc(syms, bufsize = ret);
2721 goto retry_kern_sym_load;
2722 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002723 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002724 return 0;
2725 }
2726 nksyms = nsyms = ret;
2727 ksyms = syms;
2728
2729 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2730 s->name += (unsigned long) syms;
2731 }
2732 return 1;
2733}
2734
2735
2736/* Return the kernel symbol checksum version, or zero if not used. */
2737
2738static int new_is_kernel_checksummed(void)
2739{
2740 struct new_module_symbol *s;
2741 size_t i;
2742
2743 /* Using_Versions is not the first symbol, but it should be in there. */
2744
2745 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2746 if (strcmp((char *) s->name, "Using_Versions") == 0)
2747 return s->value;
2748
2749 return 0;
2750}
2751
2752
2753static int new_create_this_module(struct obj_file *f, const char *m_name)
2754{
2755 struct obj_section *sec;
2756
2757 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002758 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002759 memset(sec->contents, 0, sizeof(struct new_module));
2760
Miles Baderae28b042002-04-01 09:34:25 +00002761 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002762 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002763 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002764
2765 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002766 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002767
2768 return 1;
2769}
2770
Eric Andersen889dd202003-01-23 04:48:34 +00002771#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2772/* add an entry to the __ksymtab section, creating it if necessary */
2773static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2774{
2775 struct obj_section *sec;
2776 ElfW(Addr) ofs;
2777
2778 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2779 * If __ksymtab is defined but not marked alloc, x out the first character
2780 * (no obj_delete routine) and create a new __ksymtab with the correct
2781 * characteristics.
2782 */
2783 sec = obj_find_section(f, "__ksymtab");
2784 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2785 *((char *)(sec->name)) = 'x'; /* override const */
2786 sec = NULL;
2787 }
2788 if (!sec)
2789 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002790 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002791 if (!sec)
2792 return;
2793 sec->header.sh_flags |= SHF_ALLOC;
2794 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002795 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002796 ofs = sec->header.sh_size;
2797 obj_symbol_patch(f, sec->idx, ofs, sym);
2798 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2799 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2800}
2801#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002802
2803static int new_create_module_ksymtab(struct obj_file *f)
2804{
2805 struct obj_section *sec;
2806 int i;
2807
2808 /* We must always add the module references. */
2809
2810 if (n_ext_modules_used) {
2811 struct new_module_ref *dep;
2812 struct obj_symbol *tm;
2813
2814 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002815 (sizeof(struct new_module_ref)
2816 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002817 if (!sec)
2818 return 0;
2819
Miles Baderae28b042002-04-01 09:34:25 +00002820 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002821 dep = (struct new_module_ref *) sec->contents;
2822 for (i = 0; i < n_ext_modules; ++i)
2823 if (ext_modules[i].used) {
2824 dep->dep = ext_modules[i].addr;
2825 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002826 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002827 dep->next_ref = 0;
2828 ++dep;
2829 }
2830 }
2831
2832 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2833 size_t nsyms;
2834 int *loaded;
2835
2836 sec =
2837 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002838 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002839
2840 /* We don't want to export symbols residing in sections that
2841 aren't loaded. There are a number of these created so that
2842 we make sure certain module options don't appear twice. */
2843
2844 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2845 while (--i >= 0)
2846 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2847
2848 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2849 struct obj_symbol *sym;
2850 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002851 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002852 && sym->secidx <= SHN_HIRESERVE
2853 && (sym->secidx >= SHN_LORESERVE
2854 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002855 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2856
2857 obj_symbol_patch(f, sec->idx, ofs, sym);
2858 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002859 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002860
2861 nsyms++;
2862 }
2863 }
2864
2865 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2866 }
2867
2868 return 1;
2869}
2870
2871
2872static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002873new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002874{
2875 struct new_module *module;
2876 struct obj_section *sec;
2877 void *image;
2878 int ret;
2879 tgt_long m_addr;
2880
2881 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002882 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002883 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002884 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002885 module = (struct new_module *) sec->contents;
2886 m_addr = sec->header.sh_addr;
2887
2888 module->size_of_struct = sizeof(*module);
2889 module->size = m_size;
2890 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2891
2892 sec = obj_find_section(f, "__ksymtab");
2893 if (sec && sec->header.sh_size) {
2894 module->syms = sec->header.sh_addr;
2895 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2896 }
2897
2898 if (n_ext_modules_used) {
2899 sec = obj_find_section(f, ".kmodtab");
2900 module->deps = sec->header.sh_addr;
2901 module->ndeps = n_ext_modules_used;
2902 }
2903
2904 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002905 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002906 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002907 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002908
2909 sec = obj_find_section(f, "__ex_table");
2910 if (sec) {
2911 module->ex_table_start = sec->header.sh_addr;
2912 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2913 }
2914
2915 sec = obj_find_section(f, ".text.init");
2916 if (sec) {
2917 module->runsize = sec->header.sh_addr - m_addr;
2918 }
2919 sec = obj_find_section(f, ".data.init");
2920 if (sec) {
2921 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002922 module->runsize > sec->header.sh_addr - m_addr)
2923 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002924 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002925 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2926 if (sec && sec->header.sh_size) {
2927 module->archdata_start = (void*)sec->header.sh_addr;
2928 module->archdata_end = module->archdata_start + sec->header.sh_size;
2929 }
2930 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2931 if (sec && sec->header.sh_size) {
2932 module->kallsyms_start = (void*)sec->header.sh_addr;
2933 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2934 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002935
Eric Andersen9f16d612000-06-12 23:11:16 +00002936 /* Whew! All of the initialization is complete. Collect the final
2937 module image and give it to the kernel. */
2938
2939 image = xmalloc(m_size);
2940 obj_create_image(f, image);
2941
Eric Andersencb3b9b12004-06-22 11:50:52 +00002942 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002943 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002944 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002945
2946 free(image);
2947
2948 return ret == 0;
2949}
2950
Eric Andersen9f16d612000-06-12 23:11:16 +00002951
2952/*======================================================================*/
2953
Eric Andersen044228d2001-07-17 01:12:36 +00002954static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002955obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2956 const char *string)
2957{
2958 struct obj_string_patch *p;
2959 struct obj_section *strsec;
2960 size_t len = strlen(string) + 1;
2961 char *loc;
2962
2963 p = xmalloc(sizeof(*p));
2964 p->next = f->string_patches;
2965 p->reloc_secidx = secidx;
2966 p->reloc_offset = offset;
2967 f->string_patches = p;
2968
2969 strsec = obj_find_section(f, ".kstrtab");
2970 if (strsec == NULL) {
2971 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2972 p->string_offset = 0;
2973 loc = strsec->contents;
2974 } else {
2975 p->string_offset = strsec->header.sh_size;
2976 loc = obj_extend_section(strsec, len);
2977 }
2978 memcpy(loc, string, len);
2979
2980 return 1;
2981}
2982
Eric Andersen044228d2001-07-17 01:12:36 +00002983static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002984obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2985 struct obj_symbol *sym)
2986{
2987 struct obj_symbol_patch *p;
2988
2989 p = xmalloc(sizeof(*p));
2990 p->next = f->symbol_patches;
2991 p->reloc_secidx = secidx;
2992 p->reloc_offset = offset;
2993 p->sym = sym;
2994 f->symbol_patches = p;
2995
2996 return 1;
2997}
2998
Eric Andersen044228d2001-07-17 01:12:36 +00002999static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003000{
3001 unsigned long i;
3002 int ret = 1;
3003
3004 for (i = 0; i < HASH_BUCKETS; ++i) {
3005 struct obj_symbol *sym;
3006 for (sym = f->symtab[i]; sym; sym = sym->next)
3007 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003008 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003009 sym->secidx = SHN_ABS;
3010 sym->value = 0;
3011 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003012 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003013 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003014 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 ret = 0;
3016 }
3017 }
3018 }
3019
3020 return ret;
3021}
3022
Eric Andersen044228d2001-07-17 01:12:36 +00003023static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003024{
3025 struct common_entry {
3026 struct common_entry *next;
3027 struct obj_symbol *sym;
3028 } *common_head = NULL;
3029
3030 unsigned long i;
3031
3032 for (i = 0; i < HASH_BUCKETS; ++i) {
3033 struct obj_symbol *sym;
3034 for (sym = f->symtab[i]; sym; sym = sym->next)
3035 if (sym->secidx == SHN_COMMON) {
3036 /* Collect all COMMON symbols and sort them by size so as to
3037 minimize space wasted by alignment requirements. */
3038 {
3039 struct common_entry **p, *n;
3040 for (p = &common_head; *p; p = &(*p)->next)
3041 if (sym->size <= (*p)->sym->size)
3042 break;
3043
3044 n = alloca(sizeof(*n));
3045 n->next = *p;
3046 n->sym = sym;
3047 *p = n;
3048 }
3049 }
3050 }
3051
3052 for (i = 1; i < f->local_symtab_size; ++i) {
3053 struct obj_symbol *sym = f->local_symtab[i];
3054 if (sym && sym->secidx == SHN_COMMON) {
3055 struct common_entry **p, *n;
3056 for (p = &common_head; *p; p = &(*p)->next)
3057 if (sym == (*p)->sym)
3058 break;
3059 else if (sym->size < (*p)->sym->size) {
3060 n = alloca(sizeof(*n));
3061 n->next = *p;
3062 n->sym = sym;
3063 *p = n;
3064 break;
3065 }
3066 }
3067 }
3068
3069 if (common_head) {
3070 /* Find the bss section. */
3071 for (i = 0; i < f->header.e_shnum; ++i)
3072 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3073 break;
3074
3075 /* If for some reason there hadn't been one, create one. */
3076 if (i == f->header.e_shnum) {
3077 struct obj_section *sec;
3078
3079 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3080 f->sections[i] = sec = arch_new_section();
3081 f->header.e_shnum = i + 1;
3082
3083 memset(sec, 0, sizeof(*sec));
3084 sec->header.sh_type = SHT_PROGBITS;
3085 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3086 sec->name = ".bss";
3087 sec->idx = i;
3088 }
3089
3090 /* Allocate the COMMONS. */
3091 {
3092 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3093 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3094 struct common_entry *c;
3095
3096 for (c = common_head; c; c = c->next) {
3097 ElfW(Addr) align = c->sym->value;
3098
3099 if (align > max_align)
3100 max_align = align;
3101 if (bss_size & (align - 1))
3102 bss_size = (bss_size | (align - 1)) + 1;
3103
3104 c->sym->secidx = i;
3105 c->sym->value = bss_size;
3106
3107 bss_size += c->sym->size;
3108 }
3109
3110 f->sections[i]->header.sh_size = bss_size;
3111 f->sections[i]->header.sh_addralign = max_align;
3112 }
3113 }
3114
3115 /* For the sake of patch relocation and parameter initialization,
3116 allocate zeroed data for NOBITS sections now. Note that after
3117 this we cannot assume NOBITS are really empty. */
3118 for (i = 0; i < f->header.e_shnum; ++i) {
3119 struct obj_section *s = f->sections[i];
3120 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003121 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003122 s->contents = memset(xmalloc(s->header.sh_size),
3123 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003124 else
3125 s->contents = NULL;
3126
Eric Andersen9f16d612000-06-12 23:11:16 +00003127 s->header.sh_type = SHT_PROGBITS;
3128 }
3129 }
3130}
3131
Eric Andersen044228d2001-07-17 01:12:36 +00003132static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003133{
3134 unsigned long dot = 0;
3135 struct obj_section *sec;
3136
3137 /* Finalize the positions of the sections relative to one another. */
3138
3139 for (sec = f->load_order; sec; sec = sec->load_next) {
3140 ElfW(Addr) align;
3141
3142 align = sec->header.sh_addralign;
3143 if (align && (dot & (align - 1)))
3144 dot = (dot | (align - 1)) + 1;
3145
3146 sec->header.sh_addr = dot;
3147 dot += sec->header.sh_size;
3148 }
3149
3150 return dot;
3151}
3152
Eric Andersen044228d2001-07-17 01:12:36 +00003153static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003154{
3155 int i, n = f->header.e_shnum;
3156 int ret = 1;
3157
3158 /* Finalize the addresses of the sections. */
3159
3160 f->baseaddr = base;
3161 for (i = 0; i < n; ++i)
3162 f->sections[i]->header.sh_addr += base;
3163
3164 /* And iterate over all of the relocations. */
3165
3166 for (i = 0; i < n; ++i) {
3167 struct obj_section *relsec, *symsec, *targsec, *strsec;
3168 ElfW(RelM) * rel, *relend;
3169 ElfW(Sym) * symtab;
3170 const char *strtab;
3171
3172 relsec = f->sections[i];
3173 if (relsec->header.sh_type != SHT_RELM)
3174 continue;
3175
3176 symsec = f->sections[relsec->header.sh_link];
3177 targsec = f->sections[relsec->header.sh_info];
3178 strsec = f->sections[symsec->header.sh_link];
3179
3180 rel = (ElfW(RelM) *) relsec->contents;
3181 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3182 symtab = (ElfW(Sym) *) symsec->contents;
3183 strtab = (const char *) strsec->contents;
3184
3185 for (; rel < relend; ++rel) {
3186 ElfW(Addr) value = 0;
3187 struct obj_symbol *intsym = NULL;
3188 unsigned long symndx;
3189 ElfW(Sym) * extsym = 0;
3190 const char *errmsg;
3191
3192 /* Attempt to find a value to use for this relocation. */
3193
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003194 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003195 if (symndx) {
3196 /* Note we've already checked for undefined symbols. */
3197
3198 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003199 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003200 /* Local symbols we look up in the local table to be sure
3201 we get the one that is really intended. */
3202 intsym = f->local_symtab[symndx];
3203 } else {
3204 /* Others we look up in the hash table. */
3205 const char *name;
3206 if (extsym->st_name)
3207 name = strtab + extsym->st_name;
3208 else
3209 name = f->sections[extsym->st_shndx]->name;
3210 intsym = obj_find_symbol(f, name);
3211 }
3212
3213 value = obj_symbol_final_value(f, intsym);
3214 intsym->referenced = 1;
3215 }
3216#if SHT_RELM == SHT_RELA
3217#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3218 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3219 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003220 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003221#endif
3222 value += rel->r_addend;
3223#endif
3224
3225 /* Do it! */
3226 switch (arch_apply_relocation
3227 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003228 case obj_reloc_ok:
3229 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003230
Eric Andersen3b1a7442003-12-24 20:30:45 +00003231 case obj_reloc_overflow:
3232 errmsg = "Relocation overflow";
3233 goto bad_reloc;
3234 case obj_reloc_dangerous:
3235 errmsg = "Dangerous relocation";
3236 goto bad_reloc;
3237 case obj_reloc_unhandled:
3238 errmsg = "Unhandled relocation";
3239bad_reloc:
3240 if (extsym) {
3241 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003242 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003243 strtab + extsym->st_name);
3244 } else {
3245 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003246 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003247 }
3248 ret = 0;
3249 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 }
3251 }
3252 }
3253
3254 /* Finally, take care of the patches. */
3255
3256 if (f->string_patches) {
3257 struct obj_string_patch *p;
3258 struct obj_section *strsec;
3259 ElfW(Addr) strsec_base;
3260 strsec = obj_find_section(f, ".kstrtab");
3261 strsec_base = strsec->header.sh_addr;
3262
3263 for (p = f->string_patches; p; p = p->next) {
3264 struct obj_section *targsec = f->sections[p->reloc_secidx];
3265 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3266 = strsec_base + p->string_offset;
3267 }
3268 }
3269
3270 if (f->symbol_patches) {
3271 struct obj_symbol_patch *p;
3272
3273 for (p = f->symbol_patches; p; p = p->next) {
3274 struct obj_section *targsec = f->sections[p->reloc_secidx];
3275 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3276 = obj_symbol_final_value(f, p->sym);
3277 }
3278 }
3279
3280 return ret;
3281}
3282
Eric Andersen044228d2001-07-17 01:12:36 +00003283static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003284{
3285 struct obj_section *sec;
3286 ElfW(Addr) base = f->baseaddr;
3287
3288 for (sec = f->load_order; sec; sec = sec->load_next) {
3289 char *secimg;
3290
Eric Andersen2bf658d2001-02-24 20:01:53 +00003291 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003292 continue;
3293
3294 secimg = image + (sec->header.sh_addr - base);
3295
3296 /* Note that we allocated data for NOBITS sections earlier. */
3297 memcpy(secimg, sec->contents, sec->header.sh_size);
3298 }
3299
3300 return 1;
3301}
3302
3303/*======================================================================*/
3304
Eric Andersen044228d2001-07-17 01:12:36 +00003305static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003306{
3307 struct obj_file *f;
3308 ElfW(Shdr) * section_headers;
3309 int shnum, i;
3310 char *shstrtab;
3311
3312 /* Read the file header. */
3313
3314 f = arch_new_file();
3315 memset(f, 0, sizeof(*f));
3316 f->symbol_cmp = strcmp;
3317 f->symbol_hash = obj_elf_hash;
3318 f->load_order_search_start = &f->load_order;
3319
3320 fseek(fp, 0, SEEK_SET);
3321 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003322 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003323 return NULL;
3324 }
3325
3326 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003327 || f->header.e_ident[EI_MAG1] != ELFMAG1
3328 || f->header.e_ident[EI_MAG2] != ELFMAG2
3329 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003330 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003331 return NULL;
3332 }
3333 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003334 || f->header.e_ident[EI_DATA] != ELFDATAM
3335 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3336 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003337 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003338 return NULL;
3339 }
3340 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003341 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003342 return NULL;
3343 }
3344
3345 /* Read the section headers. */
3346
3347 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003348 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003349 (unsigned long) f->header.e_shentsize,
3350 (unsigned long) sizeof(ElfW(Shdr)));
3351 return NULL;
3352 }
3353
3354 shnum = f->header.e_shnum;
3355 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3356 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3357
3358 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3359 fseek(fp, f->header.e_shoff, SEEK_SET);
3360 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003361 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003362 return NULL;
3363 }
3364
3365 /* Read the section data. */
3366
3367 for (i = 0; i < shnum; ++i) {
3368 struct obj_section *sec;
3369
3370 f->sections[i] = sec = arch_new_section();
3371 memset(sec, 0, sizeof(*sec));
3372
3373 sec->header = section_headers[i];
3374 sec->idx = i;
3375
Eric Andersen2bf658d2001-02-24 20:01:53 +00003376 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003377 case SHT_NULL:
3378 case SHT_NOTE:
3379 case SHT_NOBITS:
3380 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003381 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003382
3383 case SHT_PROGBITS:
3384#if LOADBITS
3385 if (!loadprogbits) {
3386 sec->contents = NULL;
3387 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003389#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003390 case SHT_SYMTAB:
3391 case SHT_STRTAB:
3392 case SHT_RELM:
3393 if (sec->header.sh_size > 0) {
3394 sec->contents = xmalloc(sec->header.sh_size);
3395 fseek(fp, sec->header.sh_offset, SEEK_SET);
3396 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3397 bb_perror_msg("error reading ELF section data");
3398 return NULL;
3399 }
3400 } else {
3401 sec->contents = NULL;
3402 }
3403 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003404
3405#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003406 case SHT_RELA:
3407 bb_error_msg("RELA relocations not supported on this architecture");
3408 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003409#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003410 case SHT_REL:
3411 bb_error_msg("REL relocations not supported on this architecture");
3412 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003413#endif
3414
Eric Andersen3b1a7442003-12-24 20:30:45 +00003415 default:
3416 if (sec->header.sh_type >= SHT_LOPROC) {
3417 /* Assume processor specific section types are debug
3418 info and can safely be ignored. If this is ever not
3419 the case (Hello MIPS?), don't put ifdefs here but
3420 create an arch_load_proc_section(). */
3421 break;
3422 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003423
Eric Andersen3b1a7442003-12-24 20:30:45 +00003424 bb_error_msg("can't handle sections of type %ld",
3425 (long) sec->header.sh_type);
3426 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003427 }
3428 }
3429
3430 /* Do what sort of interpretation as needed by each section. */
3431
3432 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3433
3434 for (i = 0; i < shnum; ++i) {
3435 struct obj_section *sec = f->sections[i];
3436 sec->name = shstrtab + sec->header.sh_name;
3437 }
3438
3439 for (i = 0; i < shnum; ++i) {
3440 struct obj_section *sec = f->sections[i];
3441
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003442 /* .modinfo should be contents only but gcc has no attribute for that.
3443 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3444 */
3445 if (strcmp(sec->name, ".modinfo") == 0)
3446 sec->header.sh_flags &= ~SHF_ALLOC;
3447
Eric Andersen9f16d612000-06-12 23:11:16 +00003448 if (sec->header.sh_flags & SHF_ALLOC)
3449 obj_insert_section_load_order(f, sec);
3450
3451 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003452 case SHT_SYMTAB:
3453 {
3454 unsigned long nsym, j;
3455 char *strtab;
3456 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003457
Eric Andersen3b1a7442003-12-24 20:30:45 +00003458 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3459 bb_error_msg("symbol size mismatch: %lu != %lu",
3460 (unsigned long) sec->header.sh_entsize,
3461 (unsigned long) sizeof(ElfW(Sym)));
3462 return NULL;
3463 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003464
Eric Andersen3b1a7442003-12-24 20:30:45 +00003465 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3466 strtab = f->sections[sec->header.sh_link]->contents;
3467 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003468
Eric Andersen3b1a7442003-12-24 20:30:45 +00003469 /* Allocate space for a table of local symbols. */
3470 j = f->local_symtab_size = sec->header.sh_info;
3471 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003472
Eric Andersen3b1a7442003-12-24 20:30:45 +00003473 /* Insert all symbols into the hash table. */
3474 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3475 ElfW(Addr) val = sym->st_value;
3476 const char *name;
3477 if (sym->st_name)
3478 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003479 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003480 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003481 else
3482 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003483
Eric Andersenbf833552003-08-13 19:56:33 +00003484#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003485 /*
3486 * For sh64 it is possible that the target of a branch
3487 * requires a mode switch (32 to 16 and back again).
3488 *
3489 * This is implied by the lsb being set in the target
3490 * address for SHmedia mode and clear for SHcompact.
3491 */
3492 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003493#endif
3494
Eric Andersen3b1a7442003-12-24 20:30:45 +00003495 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3496 val, sym->st_size);
3497 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003498 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003499 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003500
Eric Andersen3b1a7442003-12-24 20:30:45 +00003501 case SHT_RELM:
3502 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3503 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3504 (unsigned long) sec->header.sh_entsize,
3505 (unsigned long) sizeof(ElfW(RelM)));
3506 return NULL;
3507 }
3508 break;
3509 /* XXX Relocation code from modutils-2.3.19 is not here.
3510 * Why? That's about 20 lines of code from obj/obj_load.c,
3511 * which gets done in a second pass through the sections.
3512 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003513 }
3514 }
3515
3516 return f;
3517}
3518
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003519#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003520/*
3521 * load the unloaded sections directly into the memory allocated by
3522 * kernel for the module
3523 */
3524
Eric Andersenac5dbd12001-08-22 05:26:08 +00003525static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003526{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003527 ElfW(Addr) base = f->baseaddr;
3528 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003529
Eric Andersen8ae319a2001-05-21 16:09:18 +00003530 for (sec = f->load_order; sec; sec = sec->load_next) {
3531
3532 /* section already loaded? */
3533 if (sec->contents != NULL)
3534 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003535
Eric Andersen8ae319a2001-05-21 16:09:18 +00003536 if (sec->header.sh_size == 0)
3537 continue;
3538
3539 sec->contents = imagebase + (sec->header.sh_addr - base);
3540 fseek(fp, sec->header.sh_offset, SEEK_SET);
3541 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003542 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003543 return 0;
3544 }
3545
3546 }
3547 return 1;
3548}
3549#endif
3550
Eric Andersen9f16d612000-06-12 23:11:16 +00003551static void hide_special_symbols(struct obj_file *f)
3552{
3553 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003554 SPFX "cleanup_module",
3555 SPFX "init_module",
3556 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003557 NULL
3558 };
3559
3560 struct obj_symbol *sym;
3561 const char *const *p;
3562
3563 for (p = specials; *p; ++p)
3564 if ((sym = obj_find_symbol(f, *p)) != NULL)
3565 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003566 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003567}
3568
Glenn L McGrath759515c2003-08-30 06:00:33 +00003569
Eric Andersen71ae64b2002-10-10 04:20:21 +00003570#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003571static int obj_gpl_license(struct obj_file *f, const char **license)
3572{
3573 struct obj_section *sec;
3574 /* This list must match *exactly* the list of allowable licenses in
3575 * linux/include/linux/module.h. Checking for leading "GPL" will not
3576 * work, somebody will use "GPL sucks, this is proprietary".
3577 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003578 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003579 "GPL",
3580 "GPL v2",
3581 "GPL and additional rights",
3582 "Dual BSD/GPL",
3583 "Dual MPL/GPL",
3584 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003585
Eric Andersen166fa462002-09-16 05:30:24 +00003586 if ((sec = obj_find_section(f, ".modinfo"))) {
3587 const char *value, *ptr, *endptr;
3588 ptr = sec->contents;
3589 endptr = ptr + sec->header.sh_size;
3590 while (ptr < endptr) {
3591 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3592 int i;
3593 if (license)
3594 *license = value+1;
3595 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3596 if (strcmp(value+1, gpl_licenses[i]) == 0)
3597 return(0);
3598 }
3599 return(2);
3600 }
3601 if (strchr(ptr, '\0'))
3602 ptr = strchr(ptr, '\0') + 1;
3603 else
3604 ptr = endptr;
3605 }
3606 }
3607 return(1);
3608}
3609
3610#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3611#define TAINT_PROPRIETORY_MODULE (1<<0)
3612#define TAINT_FORCED_MODULE (1<<1)
3613#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003614#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003615
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003616static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003617 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3618{
3619 char buf[80];
3620 int oldval;
3621 static int first = 1;
3622 if (fd < 0 && !kernel_has_tainted)
3623 return; /* New modutils on old kernel */
3624 printf("Warning: loading %s will taint the kernel: %s%s\n",
3625 m_name, text1, text2);
3626 if (first) {
3627 printf(" See %s for information about tainted modules\n", TAINT_URL);
3628 first = 0;
3629 }
3630 if (fd >= 0) {
3631 read(fd, buf, sizeof(buf)-1);
3632 buf[sizeof(buf)-1] = '\0';
3633 oldval = strtoul(buf, NULL, 10);
3634 sprintf(buf, "%d\n", oldval | taint);
3635 write(fd, buf, strlen(buf));
3636 }
3637}
3638
3639/* Check if loading this module will taint the kernel. */
3640static void check_tainted_module(struct obj_file *f, char *m_name)
3641{
3642 static const char tainted_file[] = TAINT_FILENAME;
3643 int fd, kernel_has_tainted;
3644 const char *ptr;
3645
3646 kernel_has_tainted = 1;
3647 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3648 if (errno == ENOENT)
3649 kernel_has_tainted = 0;
3650 else if (errno == EACCES)
3651 kernel_has_tainted = 1;
3652 else {
3653 perror(tainted_file);
3654 kernel_has_tainted = 0;
3655 }
3656 }
3657
3658 switch (obj_gpl_license(f, &ptr)) {
3659 case 0:
3660 break;
3661 case 1:
3662 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3663 break;
3664 case 2:
3665 /* The module has a non-GPL license so we pretend that the
3666 * kernel always has a taint flag to get a warning even on
3667 * kernels without the proc flag.
3668 */
3669 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3670 break;
3671 default:
3672 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3673 break;
3674 }
3675
3676 if (flag_force_load)
3677 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3678
3679 if (fd >= 0)
3680 close(fd);
3681}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003682#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3683#define check_tainted_module(x, y) do { } while(0);
3684#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003685
Eric Andersen889dd202003-01-23 04:48:34 +00003686#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3687/* add module source, timestamp, kernel version and a symbol for the
3688 * start of some sections. this info is used by ksymoops to do better
3689 * debugging.
3690 */
3691static int
3692get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3693{
3694#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003695 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003696#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003697 strncpy(str, "???", sizeof(str));
3698 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003699#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3700}
3701
3702/* add module source, timestamp, kernel version and a symbol for the
3703 * start of some sections. this info is used by ksymoops to do better
3704 * debugging.
3705 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003706static void
Eric Andersen889dd202003-01-23 04:48:34 +00003707add_ksymoops_symbols(struct obj_file *f, const char *filename,
3708 const char *m_name)
3709{
3710 static const char symprefix[] = "__insmod_";
3711 struct obj_section *sec;
3712 struct obj_symbol *sym;
3713 char *name, *absolute_filename;
3714 char str[STRVERSIONLEN], real[PATH_MAX];
3715 int i, l, lm_name, lfilename, use_ksymtab, version;
3716 struct stat statbuf;
3717
3718 static const char *section_names[] = {
3719 ".text",
3720 ".rodata",
3721 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003722 ".bss",
3723 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003724 };
3725
3726 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003727 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003728 }
3729 else {
3730 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003731 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003732 errno = save_errno;
3733 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003734 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003735 }
3736
3737 lm_name = strlen(m_name);
3738 lfilename = strlen(absolute_filename);
3739
3740 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3741 * are not to be exported. otherwise leave ksymtab alone for now, the
3742 * "export all symbols" compatibility code will export these symbols later.
3743 */
3744 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3745
3746 if ((sec = obj_find_section(f, ".this"))) {
3747 /* tag the module header with the object name, last modified
3748 * timestamp and module version. worst case for module version
3749 * is 0xffffff, decimal 16777215. putting all three fields in
3750 * one symbol is less readable but saves kernel space.
3751 */
3752 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003753 lm_name+ /* module name */
3754 2+ /* "_O" */
3755 lfilename+ /* object filename */
3756 2+ /* "_M" */
3757 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3758 2+ /* "_V" */
3759 8+ /* version in dec */
3760 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003761 name = xmalloc(l);
3762 if (stat(absolute_filename, &statbuf) != 0)
3763 statbuf.st_mtime = 0;
3764 version = get_module_version(f, str); /* -1 if not found */
3765 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003766 symprefix, m_name, absolute_filename,
3767 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3768 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003769 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003770 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003771 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003772 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003773 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003774 }
3775 free(absolute_filename);
3776#ifdef _NOT_SUPPORTED_
3777 /* record where the persistent data is going, same address as previous symbol */
3778
3779 if (f->persist) {
3780 l = sizeof(symprefix)+ /* "__insmod_" */
3781 lm_name+ /* module name */
3782 2+ /* "_P" */
3783 strlen(f->persist)+ /* data store */
3784 1; /* nul */
3785 name = xmalloc(l);
3786 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003787 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003788 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003789 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003790 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003791 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003792 }
3793#endif /* _NOT_SUPPORTED_ */
3794 /* tag the desired sections if size is non-zero */
3795
3796 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3797 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003798 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003799 l = sizeof(symprefix)+ /* "__insmod_" */
3800 lm_name+ /* module name */
3801 2+ /* "_S" */
3802 strlen(sec->name)+ /* section name */
3803 2+ /* "_L" */
3804 8+ /* length in dec */
3805 1; /* nul */
3806 name = xmalloc(l);
3807 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 symprefix, m_name, sec->name,
3809 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003810 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003811 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003812 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003813 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003814 }
3815 }
3816}
3817#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3818
Eric Andersenbe65c352003-01-23 04:57:35 +00003819#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3820static void print_load_map(struct obj_file *f)
3821{
3822 struct obj_symbol *sym;
3823 struct obj_symbol **all, **p;
3824 struct obj_section *sec;
3825 int i, nsyms, *loaded;
3826
3827 /* Report on the section layout. */
3828
3829 printf("Sections: Size %-*s Align\n",
3830 (int) (2 * sizeof(void *)), "Address");
3831
3832 for (sec = f->load_order; sec; sec = sec->load_next) {
3833 int a;
3834 unsigned long tmp;
3835
3836 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3837 tmp >>= 1;
3838 if (a == -1)
3839 a = 0;
3840
3841 printf("%-15s %08lx %0*lx 2**%d\n",
3842 sec->name,
3843 (long)sec->header.sh_size,
3844 (int) (2 * sizeof(void *)),
3845 (long)sec->header.sh_addr,
3846 a);
3847 }
3848#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3849 /* Quick reference which section indicies are loaded. */
3850
3851 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3852 while (--i >= 0)
3853 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3854
3855 /* Collect the symbols we'll be listing. */
3856
3857 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3858 for (sym = f->symtab[i]; sym; sym = sym->next)
3859 if (sym->secidx <= SHN_HIRESERVE
3860 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3861 ++nsyms;
3862
3863 all = alloca(nsyms * sizeof(struct obj_symbol *));
3864
3865 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3866 for (sym = f->symtab[i]; sym; sym = sym->next)
3867 if (sym->secidx <= SHN_HIRESERVE
3868 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3869 *p++ = sym;
3870
3871 /* And list them. */
3872 printf("\nSymbols:\n");
3873 for (p = all; p < all + nsyms; ++p) {
3874 char type = '?';
3875 unsigned long value;
3876
3877 sym = *p;
3878 if (sym->secidx == SHN_ABS) {
3879 type = 'A';
3880 value = sym->value;
3881 } else if (sym->secidx == SHN_UNDEF) {
3882 type = 'U';
3883 value = 0;
3884 } else {
3885 sec = f->sections[sym->secidx];
3886
3887 if (sec->header.sh_type == SHT_NOBITS)
3888 type = 'B';
3889 else if (sec->header.sh_flags & SHF_ALLOC) {
3890 if (sec->header.sh_flags & SHF_EXECINSTR)
3891 type = 'T';
3892 else if (sec->header.sh_flags & SHF_WRITE)
3893 type = 'D';
3894 else
3895 type = 'R';
3896 }
3897 value = sym->value + sec->header.sh_addr;
3898 }
3899
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003900 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003901 type = tolower(type);
3902
3903 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3904 type, sym->name);
3905 }
3906#endif
3907}
3908
3909#endif
3910
Rob Landleydfba7412006-03-06 20:47:33 +00003911int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003912{
Eric Andersena18aaf12001-01-24 19:07:09 +00003913 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003914 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003915 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003916 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003917 unsigned long m_size;
3918 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003919 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003920 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003921 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003922 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003923 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003924#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003925 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003926 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003927 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003928#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003929#ifdef CONFIG_FEATURE_CLEAN_UP
3930 FILE *fp = 0;
3931#else
3932 FILE *fp;
3933#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003934#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3935 int flag_print_load_map = 0;
3936#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003937 int k_version = 0;
3938 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003939
Erik Andersene49d5ec2000-02-08 19:58:47 +00003940 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003941#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003942 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003943#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003944 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003945#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003946 {
3947 switch (opt) {
3948 case 'f': /* force loading */
3949 flag_force_load = 1;
3950 break;
3951 case 'k': /* module loaded by kerneld, auto-cleanable */
3952 flag_autoclean = 1;
3953 break;
3954 case 's': /* log to syslog */
3955 /* log to syslog -- not supported */
3956 /* but kernel needs this for request_module(), */
3957 /* as this calls: modprobe -k -s -- <module> */
3958 /* so silently ignore this flag */
3959 break;
3960 case 'v': /* verbose output */
3961 flag_verbose = 1;
3962 break;
3963 case 'q': /* silent */
3964 flag_quiet = 1;
3965 break;
3966 case 'x': /* do not export externs */
3967 flag_export = 0;
3968 break;
3969 case 'o': /* name the output module */
3970 free(m_name);
3971 m_name = bb_xstrdup(optarg);
3972 break;
3973 case 'L': /* Stub warning */
3974 /* This is needed for compatibility with modprobe.
3975 * In theory, this does locking, but we don't do
3976 * that. So be careful and plan your life around not
3977 * loading the same module 50 times concurrently. */
3978 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003979#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003980 case 'm': /* print module load map */
3981 flag_print_load_map = 1;
3982 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003983#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003984 default:
3985 bb_show_usage();
3986 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003987 }
Eric Andersen03d80912003-12-19 21:04:19 +00003988
Eric Andersena18aaf12001-01-24 19:07:09 +00003989 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003990 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003991 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003992
Erik Andersene49d5ec2000-02-08 19:58:47 +00003993 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003994 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003995 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003996 len = strlen(tmp);
3997
Eric Andersen03d80912003-12-19 21:04:19 +00003998 if (uname(&myuname) == 0) {
3999 if (myuname.release[0] == '2') {
4000 k_version = myuname.release[2] - '0';
4001 }
4002 }
4003
4004#if defined(CONFIG_FEATURE_2_6_MODULES)
4005 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004006 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004007 len-=3;
4008 tmp[len] = '\0';
4009 }
4010 else
4011#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004012 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4013 len-=2;
4014 tmp[len] = '\0';
4015 }
Eric Andersen2d342152002-06-18 05:16:25 +00004016
Eric Andersen03d80912003-12-19 21:04:19 +00004017
4018#if defined(CONFIG_FEATURE_2_6_MODULES)
4019 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004020 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004021 else
Eric Andersen03d80912003-12-19 21:04:19 +00004022#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004023 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004024
Eric Andersen61f83052002-06-22 17:15:42 +00004025 if (!m_name) {
4026 m_name = tmp;
4027 } else {
4028 free(tmp1);
4029 tmp1 = 0; /* flag for free(m_name) before exit() */
4030 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004031
Eric Andersen14d35432001-05-14 17:07:32 +00004032 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004033 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4034 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004035 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4036 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004037 if (k_version) { /* uname succeedd */
4038 char *module_dir;
4039 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004040 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004041
Eric Andersen03d80912003-12-19 21:04:19 +00004042 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004043 /* Jump through hoops in case /lib/modules/`uname -r`
4044 * is a symlink. We do not want recursive_action to
4045 * follow symlinks, but we do want to follow the
4046 * /lib/modules/`uname -r` dir, So resolve it ourselves
4047 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004048 if (realpath (tmdn, real_module_dir) == NULL)
4049 module_dir = tmdn;
4050 else
4051 module_dir = real_module_dir;
4052 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004053 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004054 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004055 }
4056
4057 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004058 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004059 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004060 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004061
Eric Andersen03d80912003-12-19 21:04:19 +00004062 free(m_filename);
4063 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004064 if (realpath (_PATH_MODULES, module_dir) == NULL)
4065 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004066 /* No module found under /lib/modules/`uname -r`, this
4067 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004068 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004069 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004070 {
Eric Andersen61f83052002-06-22 17:15:42 +00004071 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004072 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004073 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004074 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004075 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004076 }
4077 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004078 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004079 }
Eric Andersen03d80912003-12-19 21:04:19 +00004080 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004081 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004082
Rob Landley999af202005-12-11 20:14:12 +00004083 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004084 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004085
Eric Andersene7047882003-12-11 01:42:13 +00004086#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004087 if (k_version > 4)
4088 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004089 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004090 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004091 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004092 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004093#endif
4094
Eric Andersen8ae319a2001-05-21 16:09:18 +00004095 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004096 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004097
Eric Andersen9f16d612000-06-12 23:11:16 +00004098 if (get_modinfo_value(f, "kernel_version") == NULL)
4099 m_has_modinfo = 0;
4100 else
4101 m_has_modinfo = 1;
4102
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004103#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004104 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004105 if (!flag_quiet) {
4106 if (uname(&uts_info) < 0)
4107 uts_info.release[0] = '\0';
4108 if (m_has_modinfo) {
4109 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004110 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004111 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004112 "compiled for");
4113 goto out;
4114 }
4115 }
4116
4117 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4118 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004119 bb_error_msg("Warning: 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 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004124 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004125 "\t%s was compiled for kernel version %s\n"
4126 "\twhile this kernel is version %s.",
4127 m_filename, m_strversion, uts_info.release);
4128 goto out;
4129 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004130 }
4131 }
4132 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004133#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004134
Eric Andersencb3b9b12004-06-22 11:50:52 +00004135 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004136 if (!new_get_kernel_symbols())
4137 goto out;
4138 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004139 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004140 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004141 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004142 }
4143
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004144#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004145 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004146 if (m_has_modinfo)
4147 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004148
4149 if (m_crcs != k_crcs)
4150 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004151#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004152
Erik Andersene49d5ec2000-02-08 19:58:47 +00004153 /* Let the module know about the kernel symbols. */
4154 add_kernel_symbols(f);
4155
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 /* Allocate common symbols, symbol tables, and string tables. */
4157
Eric Andersencb3b9b12004-06-22 11:50:52 +00004158 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004159 {
4160 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004161 }
4162
Eric Andersen9f16d612000-06-12 23:11:16 +00004163 if (!obj_check_undefineds(f)) {
4164 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004165 }
4166 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004167 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004168
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004169 /* done with the module name, on to the optional var=value arguments */
4170 ++optind;
4171
Eric Andersen9f16d612000-06-12 23:11:16 +00004172 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004173 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004174 {
4175 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004176 }
4177 }
4178
Eric Andersen9f16d612000-06-12 23:11:16 +00004179 arch_create_got(f);
4180 hide_special_symbols(f);
4181
Eric Andersen889dd202003-01-23 04:48:34 +00004182#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4183 add_ksymoops_symbols(f, m_filename, m_name);
4184#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4185
Eric Andersencb3b9b12004-06-22 11:50:52 +00004186 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004187
Erik Andersene49d5ec2000-02-08 19:58:47 +00004188 /* Find current size of the module */
4189 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004190
4191
Erik Andersene49d5ec2000-02-08 19:58:47 +00004192 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004193 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004194 case EEXIST:
4195 bb_error_msg("A module named %s already exists", m_name);
4196 goto out;
4197 case ENOMEM:
4198 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4199 m_size);
4200 goto out;
4201 default:
4202 bb_perror_msg("create_module: %s", m_name);
4203 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004204 }
Erik Andersend387d011999-12-21 02:55:11 +00004205
Eric Andersen8ae319a2001-05-21 16:09:18 +00004206#if !LOADBITS
4207 /*
4208 * the PROGBITS section was not loaded by the obj_load
4209 * now we can load them directly into the kernel memory
4210 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004211 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004212 delete_module(m_name);
4213 goto out;
4214 }
Eric Andersen03d80912003-12-19 21:04:19 +00004215#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004216
Eric Andersen9f16d612000-06-12 23:11:16 +00004217 if (!obj_relocate(f, m_addr)) {
4218 delete_module(m_name);
4219 goto out;
4220 }
Erik Andersend387d011999-12-21 02:55:11 +00004221
Eric Andersencb3b9b12004-06-22 11:50:52 +00004222 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004223 {
4224 delete_module(m_name);
4225 goto out;
4226 }
4227
Eric Andersenbe65c352003-01-23 04:57:35 +00004228#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4229 if(flag_print_load_map)
4230 print_load_map(f);
4231#endif
4232
Matt Kraai3e856ce2000-12-01 02:55:13 +00004233 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004234
4235out:
Eric Andersen61f83052002-06-22 17:15:42 +00004236#ifdef CONFIG_FEATURE_CLEAN_UP
4237 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004238 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004239 free(tmp1);
4240 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004241 free(m_name);
4242 }
4243 free(m_filename);
4244#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004245 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004246}
Eric Andersene7047882003-12-11 01:42:13 +00004247
4248
4249#endif
4250
4251
4252#ifdef CONFIG_FEATURE_2_6_MODULES
4253
4254#include <sys/mman.h>
4255#include <asm/unistd.h>
4256#include <sys/syscall.h>
4257
4258/* We use error numbers in a loose translation... */
4259static const char *moderror(int err)
4260{
4261 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004262 case ENOEXEC:
4263 return "Invalid module format";
4264 case ENOENT:
4265 return "Unknown symbol in module";
4266 case ESRCH:
4267 return "Module has wrong symbol version";
4268 case EINVAL:
4269 return "Invalid parameters";
4270 default:
4271 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004272 }
4273}
4274
Rob Landleydfba7412006-03-06 20:47:33 +00004275int insmod_ng_main( int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004276{
4277 int i;
4278 int fd;
4279 long int ret;
4280 struct stat st;
4281 unsigned long len;
4282 void *map;
4283 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004284
Eric Andersene7047882003-12-11 01:42:13 +00004285 filename = argv[1];
4286 if (!filename) {
4287 bb_show_usage();
4288 return -1;
4289 }
4290
4291 /* Rest is options */
4292 for (i = 2; i < argc; i++) {
4293 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4294 /* Spaces handled by "" pairs, but no way of escaping quotes */
4295 if (strchr(argv[i], ' ')) {
4296 strcat(options, "\"");
4297 strcat(options, argv[i]);
4298 strcat(options, "\"");
4299 } else {
4300 strcat(options, argv[i]);
4301 }
4302 strcat(options, " ");
4303 }
4304
4305 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4306 bb_perror_msg_and_die("cannot open module `%s'", filename);
4307 }
4308
4309 fstat(fd, &st);
4310 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004311 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004312 if (map == MAP_FAILED) {
4313 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4314 }
4315
4316 ret = syscall(__NR_init_module, map, len, options);
4317 if (ret != 0) {
4318 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004319 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004320 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004321
Eric Andersene7047882003-12-11 01:42:13 +00004322 return 0;
4323}
4324
4325#endif