blob: 14322d978831a986c8d92c25da76b00a724b27b5 [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
Mark Whitley59ab0252001-01-23 22:30:04 +0000346static 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
Mark Whitley59ab0252001-01-23 22:30:04 +0000367static const int tgt_sizeof_long = 8;
368static const int tgt_sizeof_char_p = 8;
369static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000370#define tgt_long long long
371#endif
372
373/*======================================================================*/
374/* The structures used in Linux 2.1. */
375
376/* Note: new_module_symbol does not use tgt_long intentionally */
377struct new_module_symbol
378{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000379 unsigned long value;
380 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000381};
382
383struct new_module_persist;
384
385struct new_module_ref
386{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000387 unsigned tgt_long dep; /* kernel addresses */
388 unsigned tgt_long ref;
389 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000390};
391
392struct new_module
393{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000394 unsigned tgt_long size_of_struct; /* == sizeof(module) */
395 unsigned tgt_long next;
396 unsigned tgt_long name;
397 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000398
Eric Andersen3b1a7442003-12-24 20:30:45 +0000399 tgt_long usecount;
400 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000401
Eric Andersen3b1a7442003-12-24 20:30:45 +0000402 unsigned nsyms;
403 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 unsigned tgt_long syms;
406 unsigned tgt_long deps;
407 unsigned tgt_long refs;
408 unsigned tgt_long init;
409 unsigned tgt_long cleanup;
410 unsigned tgt_long ex_table_start;
411 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000412#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000413 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000414#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000415 /* Everything after here is extension. */
416 unsigned tgt_long persist_start;
417 unsigned tgt_long persist_end;
418 unsigned tgt_long can_unload;
419 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000420 const char *kallsyms_start; /* All symbols for kernel debugging */
421 const char *kallsyms_end;
422 const char *archdata_start; /* arch specific data for module */
423 const char *archdata_end;
424 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000425};
426
Eric Andersencffd5022002-05-24 06:50:15 +0000427#ifdef ARCHDATAM
428#define ARCHDATA_SEC_NAME ARCHDATAM
429#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000430#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000431#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000432#define KALLSYMS_SEC_NAME "__kallsyms"
433
434
Eric Andersen9f16d612000-06-12 23:11:16 +0000435struct new_module_info
436{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000437 unsigned long addr;
438 unsigned long size;
439 unsigned long flags;
440 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000441};
442
443/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000444static const int NEW_MOD_RUNNING = 1;
445static const int NEW_MOD_DELETED = 2;
446static const int NEW_MOD_AUTOCLEAN = 4;
447static const int NEW_MOD_VISITED = 8;
448static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000449
Eric Andersencb3b9b12004-06-22 11:50:52 +0000450int init_module(const char *name, const struct new_module *);
451int query_module(const char *name, int which, void *buf,
452 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
454/* Values for query_module's which. */
455
Mark Whitley59ab0252001-01-23 22:30:04 +0000456static const int QM_MODULES = 1;
457static const int QM_DEPS = 2;
458static const int QM_REFS = 3;
459static const int QM_SYMBOLS = 4;
460static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000461
462/*======================================================================*/
463/* The system calls unchanged between 2.0 and 2.1. */
464
465unsigned long create_module(const char *, size_t);
466int delete_module(const char *);
467
468
469#endif /* module.h */
470
471//----------------------------------------------------------------------------
472//--------end of modutils module.h
473//----------------------------------------------------------------------------
474
475
476
477//----------------------------------------------------------------------------
478//--------modutils obj.h, lines 253-462
479//----------------------------------------------------------------------------
480
481/* Elf object file loading and relocation routines.
482 Copyright 1996, 1997 Linux International.
483
484 Contributed by Richard Henderson <rth@tamu.edu>
485
486 This file is part of the Linux modutils.
487
488 This program is free software; you can redistribute it and/or modify it
489 under the terms of the GNU General Public License as published by the
490 Free Software Foundation; either version 2 of the License, or (at your
491 option) any later version.
492
493 This program is distributed in the hope that it will be useful, but
494 WITHOUT ANY WARRANTY; without even the implied warranty of
495 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
496 General Public License for more details.
497
498 You should have received a copy of the GNU General Public License
499 along with this program; if not, write to the Free Software Foundation,
500 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
501
502
503#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000504static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000505
Mike Frysinger63654c12004-12-26 09:13:32 +0000506#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000507
508/* The relocatable object is manipulated using elfin types. */
509
510#include <stdio.h>
511#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000512#include <endian.h>
513
Rob Landley688ed0d2006-03-04 22:40:25 +0000514#if BB_LITTLE_ENDIAN
515# define ELFDATAM ELFDATA2LSB
516#else
517# define ELFDATAM ELFDATA2MSB
Eric Andersenb1591d12002-04-12 00:28:59 +0000518#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000519
Eric Andersen9f16d612000-06-12 23:11:16 +0000520#ifndef ElfW
521# if ELFCLASSM == ELFCLASS32
522# define ElfW(x) Elf32_ ## x
523# define ELFW(x) ELF32_ ## x
524# else
525# define ElfW(x) Elf64_ ## x
526# define ELFW(x) ELF64_ ## x
527# endif
528#endif
529
Eric Andersen85e5e722003-07-22 08:56:55 +0000530/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000531#ifndef ELF32_ST_INFO
532# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
533#endif
534
535#ifndef ELF64_ST_INFO
536# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
537#endif
538
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000539#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
540#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
541#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
542#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
543#define ELF_R_SYM(val) ELFW(R_SYM)(val)
544
Eric Andersen9f16d612000-06-12 23:11:16 +0000545struct obj_string_patch;
546struct obj_symbol_patch;
547
548struct obj_section
549{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000550 ElfW(Shdr) header;
551 const char *name;
552 char *contents;
553 struct obj_section *load_next;
554 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000555};
556
557struct obj_symbol
558{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000559 struct obj_symbol *next; /* hash table link */
560 const char *name;
561 unsigned long value;
562 unsigned long size;
563 int secidx; /* the defining section index/module */
564 int info;
565 int ksymidx; /* for export to the kernel symtab */
566 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000567};
568
569/* Hardcode the hash table size. We shouldn't be needing so many
570 symbols that we begin to degrade performance, and we get a big win
571 by giving the compiler a constant divisor. */
572
573#define HASH_BUCKETS 521
574
575struct obj_file
576{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000577 ElfW(Ehdr) header;
578 ElfW(Addr) baseaddr;
579 struct obj_section **sections;
580 struct obj_section *load_order;
581 struct obj_section **load_order_search_start;
582 struct obj_string_patch *string_patches;
583 struct obj_symbol_patch *symbol_patches;
584 int (*symbol_cmp)(const char *, const char *);
585 unsigned long (*symbol_hash)(const char *);
586 unsigned long local_symtab_size;
587 struct obj_symbol **local_symtab;
588 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000589};
590
591enum obj_reloc
592{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000593 obj_reloc_ok,
594 obj_reloc_overflow,
595 obj_reloc_dangerous,
596 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000597};
598
599struct obj_string_patch
600{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000601 struct obj_string_patch *next;
602 int reloc_secidx;
603 ElfW(Addr) reloc_offset;
604 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000605};
606
607struct obj_symbol_patch
608{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000609 struct obj_symbol_patch *next;
610 int reloc_secidx;
611 ElfW(Addr) reloc_offset;
612 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000613};
614
615
616/* Generic object manipulation routines. */
617
Eric Andersen044228d2001-07-17 01:12:36 +0000618static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000619
Eric Andersen044228d2001-07-17 01:12:36 +0000620static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000621
Eric Andersen044228d2001-07-17 01:12:36 +0000622static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000623 const char *name);
624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000626 struct obj_symbol *sym);
627
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000628#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000629static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000630 int (*cmp)(const char *, const char *),
631 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000632#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000633
Eric Andersen044228d2001-07-17 01:12:36 +0000634static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000635 const char *name);
636
Eric Andersen044228d2001-07-17 01:12:36 +0000637static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000638 struct obj_section *sec);
639
Eric Andersen044228d2001-07-17 01:12:36 +0000640static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000641 const char *name,
642 unsigned long align,
643 unsigned long size);
644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static struct obj_section *obj_create_alloced_section_first (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 void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Eric Andersen044228d2001-07-17 01:12:36 +0000652static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000653 const char *string);
654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 struct obj_symbol *sym);
657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen044228d2001-07-17 01:12:36 +0000662static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000663
Eric Andersen044228d2001-07-17 01:12:36 +0000664static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000665
Eric Andersen044228d2001-07-17 01:12:36 +0000666static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000667
Eric Andersen044228d2001-07-17 01:12:36 +0000668static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000669
670/* Architecture specific manipulation routines. */
671
Eric Andersen044228d2001-07-17 01:12:36 +0000672static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000673
Eric Andersen044228d2001-07-17 01:12:36 +0000674static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000675
Eric Andersen044228d2001-07-17 01:12:36 +0000676static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000677
Eric Andersen044228d2001-07-17 01:12:36 +0000678static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000679 struct obj_section *targsec,
680 struct obj_section *symsec,
681 struct obj_symbol *sym,
682 ElfW(RelM) *rel, ElfW(Addr) value);
683
Eric Andersencffd5022002-05-24 06:50:15 +0000684static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000685
Glenn L McGrath759515c2003-08-30 06:00:33 +0000686static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000687
Eric Andersen9f16d612000-06-12 23:11:16 +0000688#endif /* obj.h */
689//----------------------------------------------------------------------------
690//--------end of modutils obj.h
691//----------------------------------------------------------------------------
692
693
Miles Baderae28b042002-04-01 09:34:25 +0000694/* SPFX is always a string, so it can be concatenated to string constants. */
695#ifdef SYMBOL_PREFIX
696#define SPFX SYMBOL_PREFIX
697#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000698#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000699#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000700
Erik Andersen02104321999-12-17 18:57:34 +0000701
Erik Andersend387d011999-12-21 02:55:11 +0000702#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000703static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000704
Eric Andersen9f16d612000-06-12 23:11:16 +0000705/*======================================================================*/
706
Eric Andersen044228d2001-07-17 01:12:36 +0000707static int flag_force_load = 0;
708static int flag_autoclean = 0;
709static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000710static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000711static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000712
713
714/*======================================================================*/
715
Eric Andersencffd5022002-05-24 06:50:15 +0000716#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000717
Eric Andersencffd5022002-05-24 06:50:15 +0000718struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000719{
Eric Andersencffd5022002-05-24 06:50:15 +0000720 struct arch_list_entry *next;
721 CONFIG_LIST_ARCHTYPE addend;
722 int offset;
723 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000724};
Eric Andersencffd5022002-05-24 06:50:15 +0000725
Eric Andersen21adca72000-12-06 18:18:26 +0000726#endif
727
Eric Andersencffd5022002-05-24 06:50:15 +0000728#if defined(CONFIG_USE_SINGLE)
729
730struct arch_single_entry
731{
Eric Andersen9f16d612000-06-12 23:11:16 +0000732 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000733 int inited : 1;
734 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000735};
Eric Andersencffd5022002-05-24 06:50:15 +0000736
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000737#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000738
Eric Andersen2bf658d2001-02-24 20:01:53 +0000739#if defined(__mips__)
740struct mips_hi16
741{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000742 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000743 ElfW(Addr) *addr;
744 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000745};
746#endif
747
Eric Andersenfe4208f2000-09-24 03:44:29 +0000748struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000749 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000750#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000751 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000752#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000753#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000756#if defined(__mips__)
757 struct mips_hi16 *mips_hi16_list;
758#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000759};
760
Eric Andersenfe4208f2000-09-24 03:44:29 +0000761struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000762 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000763#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000764#if defined(CONFIG_USE_PLT_LIST)
765 struct arch_list_entry *pltent;
766#else
767 struct arch_single_entry pltent;
768#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000769#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000770#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000771 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000772#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000773};
774
775
Eric Andersen9f16d612000-06-12 23:11:16 +0000776struct external_module {
777 const char *name;
778 ElfW(Addr) addr;
779 int used;
780 size_t nsyms;
781 struct new_module_symbol *syms;
782};
783
Eric Andersen044228d2001-07-17 01:12:36 +0000784static struct new_module_symbol *ksyms;
785static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000786
Eric Andersen044228d2001-07-17 01:12:36 +0000787static struct external_module *ext_modules;
788static int n_ext_modules;
789static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000790extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000791
Eric Andersen61f83052002-06-22 17:15:42 +0000792static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000793static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000794
Eric Andersenfe4208f2000-09-24 03:44:29 +0000795
Erik Andersen02104321999-12-17 18:57:34 +0000796
Eric Andersen9f16d612000-06-12 23:11:16 +0000797/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000798
Eric Andersen9f16d612000-06-12 23:11:16 +0000799
Eric Andersen14d35432001-05-14 17:07:32 +0000800static int check_module_name_match(const char *filename, struct stat *statbuf,
801 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000802{
Eric Andersen14d35432001-05-14 17:07:32 +0000803 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000804
Eric Andersen14d35432001-05-14 17:07:32 +0000805 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000806 return (FALSE);
807 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000808 char *tmp, *tmp1 = bb_xstrdup(filename);
809 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000810 if (strcmp(tmp, fullname) == 0) {
811 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000812 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000813 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000814 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000815 }
Eric Andersen14d35432001-05-14 17:07:32 +0000816 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000817 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000818 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000819}
820
Erik Andersen02104321999-12-17 18:57:34 +0000821
Eric Andersen9f16d612000-06-12 23:11:16 +0000822/*======================================================================*/
823
Eric Andersen044228d2001-07-17 01:12:36 +0000824static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000825{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000826 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000827 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828
Eric Andersencffd5022002-05-24 06:50:15 +0000829 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 return &f->root;
832}
833
Eric Andersen044228d2001-07-17 01:12:36 +0000834static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000835{
836 return xmalloc(sizeof(struct obj_section));
837}
838
Eric Andersen044228d2001-07-17 01:12:36 +0000839static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000840{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000841 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000842 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000843
Eric Andersencffd5022002-05-24 06:50:15 +0000844 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000845
Eric Andersen9f16d612000-06-12 23:11:16 +0000846 return &sym->root;
847}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000848
Eric Andersen044228d2001-07-17 01:12:36 +0000849static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000850arch_apply_relocation(struct obj_file *f,
851 struct obj_section *targsec,
852 struct obj_section *symsec,
853 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000854 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000855{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000856 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000857 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000858 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
859 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000860#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
861 struct arch_symbol *isym = (struct arch_symbol *) sym;
862#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000863#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000864#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000865 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000866#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000867#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000868#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000869 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000870 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000871# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000872 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000873# else
Eric Andersencffd5022002-05-24 06:50:15 +0000874 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000875# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000876#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000877
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000878 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000879
Eric Andersencffd5022002-05-24 06:50:15 +0000880#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000881
Eric Andersen3b1a7442003-12-24 20:30:45 +0000882 case R_ARM_NONE:
883 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000884
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 case R_ARM_ABS32:
886 *loc += v;
887 break;
Miles Baderae28b042002-04-01 09:34:25 +0000888
Eric Andersen3b1a7442003-12-24 20:30:45 +0000889 case R_ARM_GOT32:
890 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000891
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000893 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
894 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000896
Eric Andersen3496fdc2006-01-30 23:09:20 +0000897 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000898 *loc += got - dot;
899 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000900
Eric Andersen3b1a7442003-12-24 20:30:45 +0000901 case R_ARM_PC24:
902 case R_ARM_PLT32:
903 goto bb_use_plt;
904
905 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3496fdc2006-01-30 23:09:20 +0000906 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000907 *loc += v - got;
908 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000909
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000910#elif defined(__cris__)
911
912 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000913 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000914
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915 case R_CRIS_32:
916 /* CRIS keeps the relocation value in the r_addend field and
917 * should not use whats in *loc at all
918 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000919 *loc = v;
920 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000921
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000922#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000923
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000924 case R_H8_DIR24R8:
925 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
926 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000927 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000928 case R_H8_DIR24A8:
929 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000930 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000931 case R_H8_DIR32:
932 case R_H8_DIR32A16:
933 *loc += v;
934 break;
935 case R_H8_PCREL16:
936 v -= dot + 2;
937 if ((ElfW(Sword))v > 0x7fff ||
938 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
939 ret = obj_reloc_overflow;
940 else
941 *(unsigned short *)loc = v;
942 break;
943 case R_H8_PCREL8:
944 v -= dot + 1;
945 if ((ElfW(Sword))v > 0x7f ||
946 (ElfW(Sword))v < -(ElfW(Sword))0x80)
947 ret = obj_reloc_overflow;
948 else
949 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000950 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000951
Eric Andersencffd5022002-05-24 06:50:15 +0000952#elif defined(__i386__)
953
Eric Andersen3b1a7442003-12-24 20:30:45 +0000954 case R_386_NONE:
955 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000956
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 case R_386_32:
958 *loc += v;
959 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000960
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 case R_386_PLT32:
962 case R_386_PC32:
963 *loc += v - dot;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GLOB_DAT:
967 case R_386_JMP_SLOT:
968 *loc = v;
969 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000970
Eric Andersen3b1a7442003-12-24 20:30:45 +0000971 case R_386_RELATIVE:
972 *loc += f->baseaddr;
973 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000974
Eric Andersen3b1a7442003-12-24 20:30:45 +0000975 case R_386_GOTPC:
976 assert(got != 0);
977 *loc += got - dot;
978 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000979
Eric Andersen3b1a7442003-12-24 20:30:45 +0000980 case R_386_GOT32:
981 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000982
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 case R_386_GOTOFF:
984 assert(got != 0);
985 *loc += v - got;
986 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000987
988#elif defined(__mc68000__)
989
Eric Andersen3b1a7442003-12-24 20:30:45 +0000990 case R_68K_NONE:
991 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000992
Eric Andersen3b1a7442003-12-24 20:30:45 +0000993 case R_68K_32:
994 *loc += v;
995 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000996
Eric Andersen3b1a7442003-12-24 20:30:45 +0000997 case R_68K_8:
998 if (v > 0xff) {
999 ret = obj_reloc_overflow;
1000 }
1001 *(char *)loc = v;
1002 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001003
Eric Andersen3b1a7442003-12-24 20:30:45 +00001004 case R_68K_16:
1005 if (v > 0xffff) {
1006 ret = obj_reloc_overflow;
1007 }
1008 *(short *)loc = v;
1009 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001010
Eric Andersen3b1a7442003-12-24 20:30:45 +00001011 case R_68K_PC8:
1012 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001013 if ((ElfW(Sword))v > 0x7f ||
1014 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001015 ret = obj_reloc_overflow;
1016 }
1017 *(char *)loc = v;
1018 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001019
Eric Andersen3b1a7442003-12-24 20:30:45 +00001020 case R_68K_PC16:
1021 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001022 if ((ElfW(Sword))v > 0x7fff ||
1023 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001024 ret = obj_reloc_overflow;
1025 }
1026 *(short *)loc = v;
1027 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001028
Eric Andersen3b1a7442003-12-24 20:30:45 +00001029 case R_68K_PC32:
1030 *(int *)loc = v - dot;
1031 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001032
Eric Andersen3b1a7442003-12-24 20:30:45 +00001033 case R_68K_GLOB_DAT:
1034 case R_68K_JMP_SLOT:
1035 *loc = v;
1036 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001037
Eric Andersen3b1a7442003-12-24 20:30:45 +00001038 case R_68K_RELATIVE:
1039 *(int *)loc += f->baseaddr;
1040 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001041
Eric Andersen3b1a7442003-12-24 20:30:45 +00001042 case R_68K_GOT32:
1043 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001044
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001045# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_GOTOFF:
1047 assert(got != 0);
1048 *loc += v - got;
1049 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001050# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001051
1052#elif defined(__mips__)
1053
Eric Andersen3b1a7442003-12-24 20:30:45 +00001054 case R_MIPS_NONE:
1055 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001056
Eric Andersen3b1a7442003-12-24 20:30:45 +00001057 case R_MIPS_32:
1058 *loc += v;
1059 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001060
Eric Andersen3b1a7442003-12-24 20:30:45 +00001061 case R_MIPS_26:
1062 if (v % 4)
1063 ret = obj_reloc_dangerous;
1064 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1065 ret = obj_reloc_overflow;
1066 *loc =
1067 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1068 0x03ffffff);
1069 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001070
Eric Andersen3b1a7442003-12-24 20:30:45 +00001071 case R_MIPS_HI16:
1072 {
1073 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001074
Eric Andersen3b1a7442003-12-24 20:30:45 +00001075 /* We cannot relocate this one now because we don't know the value
1076 of the carry we need to add. Save the information, and let LO16
1077 do the actual relocation. */
1078 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1079 n->addr = loc;
1080 n->value = v;
1081 n->next = ifile->mips_hi16_list;
1082 ifile->mips_hi16_list = n;
1083 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001084 }
1085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_MIPS_LO16:
1087 {
1088 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001089 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001090
1091 /* Sign extend the addend we extract from the lo insn. */
1092 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1093
1094 if (ifile->mips_hi16_list != NULL) {
1095 struct mips_hi16 *l;
1096
1097 l = ifile->mips_hi16_list;
1098 while (l != NULL) {
1099 struct mips_hi16 *next;
1100 unsigned long insn;
1101
1102 /* The value for the HI16 had best be the same. */
1103 assert(v == l->value);
1104
1105 /* Do the HI16 relocation. Note that we actually don't
1106 need to know anything about the LO16 itself, except where
1107 to find the low 16 bits of the addend needed by the LO16. */
1108 insn = *l->addr;
1109 val =
1110 ((insn & 0xffff) << 16) +
1111 vallo;
1112 val += v;
1113
1114 /* Account for the sign extension that will happen in the
1115 low bits. */
1116 val =
1117 ((val >> 16) +
1118 ((val & 0x8000) !=
1119 0)) & 0xffff;
1120
1121 insn = (insn & ~0xffff) | val;
1122 *l->addr = insn;
1123
1124 next = l->next;
1125 free(l);
1126 l = next;
1127 }
1128
1129 ifile->mips_hi16_list = NULL;
1130 }
1131
1132 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1133 val = v + vallo;
1134 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1135 *loc = insnlo;
1136 break;
1137 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001138
Mike Frysingerf982d862006-01-04 00:11:26 +00001139#elif defined(__nios2__)
1140
1141 case R_NIOS2_NONE:
1142 break;
1143
1144 case R_NIOS2_BFD_RELOC_32:
1145 *loc += v;
1146 break;
1147
1148 case R_NIOS2_BFD_RELOC_16:
1149 if (v > 0xffff) {
1150 ret = obj_reloc_overflow;
1151 }
1152 *(short *)loc = v;
1153 break;
1154
1155 case R_NIOS2_BFD_RELOC_8:
1156 if (v > 0xff) {
1157 ret = obj_reloc_overflow;
1158 }
1159 *(char *)loc = v;
1160 break;
1161
1162 case R_NIOS2_S16:
1163 {
1164 Elf32_Addr word;
1165
1166 if ((Elf32_Sword)v > 0x7fff ||
1167 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1168 ret = obj_reloc_overflow;
1169 }
1170
1171 word = *loc;
1172 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1173 (word & 0x3f);
1174 }
1175 break;
1176
1177 case R_NIOS2_U16:
1178 {
1179 Elf32_Addr word;
1180
1181 if (v > 0xffff) {
1182 ret = obj_reloc_overflow;
1183 }
1184
1185 word = *loc;
1186 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1187 (word & 0x3f);
1188 }
1189 break;
1190
1191 case R_NIOS2_PCREL16:
1192 {
1193 Elf32_Addr word;
1194
1195 v -= dot + 4;
1196 if ((Elf32_Sword)v > 0x7fff ||
1197 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1198 ret = obj_reloc_overflow;
1199 }
1200
1201 word = *loc;
1202 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1203 }
1204 break;
1205
1206 case R_NIOS2_GPREL:
1207 {
1208 Elf32_Addr word, gp;
1209 /* get _gp */
1210 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1211 v-=gp;
1212 if ((Elf32_Sword)v > 0x7fff ||
1213 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1214 ret = obj_reloc_overflow;
1215 }
1216
1217 word = *loc;
1218 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1219 }
1220 break;
1221
1222 case R_NIOS2_CALL26:
1223 if (v & 3)
1224 ret = obj_reloc_dangerous;
1225 if ((v >> 28) != (dot >> 28))
1226 ret = obj_reloc_overflow;
1227 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1228 break;
1229
1230 case R_NIOS2_IMM5:
1231 {
1232 Elf32_Addr word;
1233
1234 if (v > 0x1f) {
1235 ret = obj_reloc_overflow;
1236 }
1237
1238 word = *loc & ~0x7c0;
1239 *loc = word | ((v & 0x1f) << 6);
1240 }
1241 break;
1242
1243 case R_NIOS2_IMM6:
1244 {
1245 Elf32_Addr word;
1246
1247 if (v > 0x3f) {
1248 ret = obj_reloc_overflow;
1249 }
1250
1251 word = *loc & ~0xfc0;
1252 *loc = word | ((v & 0x3f) << 6);
1253 }
1254 break;
1255
1256 case R_NIOS2_IMM8:
1257 {
1258 Elf32_Addr word;
1259
1260 if (v > 0xff) {
1261 ret = obj_reloc_overflow;
1262 }
1263
1264 word = *loc & ~0x3fc0;
1265 *loc = word | ((v & 0xff) << 6);
1266 }
1267 break;
1268
1269 case R_NIOS2_HI16:
1270 {
1271 Elf32_Addr word;
1272
1273 word = *loc;
1274 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1275 (word & 0x3f);
1276 }
1277 break;
1278
1279 case R_NIOS2_LO16:
1280 {
1281 Elf32_Addr word;
1282
1283 word = *loc;
1284 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1285 (word & 0x3f);
1286 }
1287 break;
1288
1289 case R_NIOS2_HIADJ16:
1290 {
1291 Elf32_Addr word1, word2;
1292
1293 word1 = *loc;
1294 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1295 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1296 (word1 & 0x3f);
1297 }
1298 break;
1299
Mike Frysingerebee0e72006-02-18 06:14:31 +00001300#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001301 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001302
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001303#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001304
Eric Andersen3b1a7442003-12-24 20:30:45 +00001305 case R_PPC_ADDR16_HA:
1306 *(unsigned short *)loc = (v + 0x8000) >> 16;
1307 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001308
Eric Andersen3b1a7442003-12-24 20:30:45 +00001309 case R_PPC_ADDR16_HI:
1310 *(unsigned short *)loc = v >> 16;
1311 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001312
Eric Andersen3b1a7442003-12-24 20:30:45 +00001313 case R_PPC_ADDR16_LO:
1314 *(unsigned short *)loc = v;
1315 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001316
Eric Andersen3b1a7442003-12-24 20:30:45 +00001317 case R_PPC_REL24:
1318 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001319
Eric Andersen3b1a7442003-12-24 20:30:45 +00001320 case R_PPC_REL32:
1321 *loc = v - dot;
1322 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001323
Eric Andersen3b1a7442003-12-24 20:30:45 +00001324 case R_PPC_ADDR32:
1325 *loc = v;
1326 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001327
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001328#elif defined(__s390__)
1329
1330 case R_390_32:
1331 *(unsigned int *) loc += v;
1332 break;
1333 case R_390_16:
1334 *(unsigned short *) loc += v;
1335 break;
1336 case R_390_8:
1337 *(unsigned char *) loc += v;
1338 break;
1339
1340 case R_390_PC32:
1341 *(unsigned int *) loc += v - dot;
1342 break;
1343 case R_390_PC16DBL:
1344 *(unsigned short *) loc += (v - dot) >> 1;
1345 break;
1346 case R_390_PC16:
1347 *(unsigned short *) loc += v - dot;
1348 break;
1349
1350 case R_390_PLT32:
1351 case R_390_PLT16DBL:
1352 /* find the plt entry and initialize it. */
1353 assert(isym != NULL);
1354 pe = (struct arch_single_entry *) &isym->pltent;
1355 assert(pe->allocated);
1356 if (pe->inited == 0) {
1357 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1358 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1359 ip[1] = 0x100607f1;
1360 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1361 ip[2] = v - 2;
1362 else
1363 ip[2] = v;
1364 pe->inited = 1;
1365 }
1366
1367 /* Insert relative distance to target. */
1368 v = plt + pe->offset - dot;
1369 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1370 *(unsigned int *) loc = (unsigned int) v;
1371 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1372 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1373 break;
1374
1375 case R_390_GLOB_DAT:
1376 case R_390_JMP_SLOT:
1377 *loc = v;
1378 break;
1379
1380 case R_390_RELATIVE:
1381 *loc += f->baseaddr;
1382 break;
1383
1384 case R_390_GOTPC:
1385 assert(got != 0);
1386 *(unsigned long *) loc += got - dot;
1387 break;
1388
1389 case R_390_GOT12:
1390 case R_390_GOT16:
1391 case R_390_GOT32:
1392 assert(isym != NULL);
1393 assert(got != 0);
1394 if (!isym->gotent.inited)
1395 {
1396 isym->gotent.inited = 1;
1397 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1398 }
1399 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1400 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1401 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1402 *(unsigned short *) loc += isym->gotent.offset;
1403 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1404 *(unsigned int *) loc += isym->gotent.offset;
1405 break;
1406
1407# ifndef R_390_GOTOFF32
1408# define R_390_GOTOFF32 R_390_GOTOFF
1409# endif
1410 case R_390_GOTOFF32:
1411 assert(got != 0);
1412 *loc += v - got;
1413 break;
1414
Eric Andersencffd5022002-05-24 06:50:15 +00001415#elif defined(__sh__)
1416
Eric Andersen3b1a7442003-12-24 20:30:45 +00001417 case R_SH_NONE:
1418 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001419
Eric Andersen3b1a7442003-12-24 20:30:45 +00001420 case R_SH_DIR32:
1421 *loc += v;
1422 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001423
Eric Andersen3b1a7442003-12-24 20:30:45 +00001424 case R_SH_REL32:
1425 *loc += v - dot;
1426 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001427
Eric Andersen3b1a7442003-12-24 20:30:45 +00001428 case R_SH_PLT32:
1429 *loc = v - dot;
1430 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001431
Eric Andersen3b1a7442003-12-24 20:30:45 +00001432 case R_SH_GLOB_DAT:
1433 case R_SH_JMP_SLOT:
1434 *loc = v;
1435 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001436
Eric Andersen3b1a7442003-12-24 20:30:45 +00001437 case R_SH_RELATIVE:
1438 *loc = f->baseaddr + rel->r_addend;
1439 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001440
Eric Andersen3b1a7442003-12-24 20:30:45 +00001441 case R_SH_GOTPC:
1442 assert(got != 0);
1443 *loc = got - dot + rel->r_addend;
1444 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001445
Eric Andersen3b1a7442003-12-24 20:30:45 +00001446 case R_SH_GOT32:
1447 goto bb_use_got;
1448
1449 case R_SH_GOTOFF:
1450 assert(got != 0);
1451 *loc = v - got;
1452 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001453
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001454# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001455 case R_SH_IMM_MEDLOW16:
1456 case R_SH_IMM_LOW16:
1457 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001458 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001459
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001460 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001461 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001462
Eric Andersen3b1a7442003-12-24 20:30:45 +00001463 /*
1464 * movi and shori have the format:
1465 *
1466 * | op | imm | reg | reserved |
1467 * 31..26 25..10 9.. 4 3 .. 0
1468 *
1469 * so we simply mask and or in imm.
1470 */
1471 word = *loc & ~0x3fffc00;
1472 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001473
Eric Andersen3b1a7442003-12-24 20:30:45 +00001474 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 break;
1477 }
Eric Andersenbf833552003-08-13 19:56:33 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 case R_SH_IMM_MEDLOW16_PCREL:
1480 case R_SH_IMM_LOW16_PCREL:
1481 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001482 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001483
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001485
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001487
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001488 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001490
Eric Andersen3b1a7442003-12-24 20:30:45 +00001491 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001492
Eric Andersen3b1a7442003-12-24 20:30:45 +00001493 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001494
Eric Andersen3b1a7442003-12-24 20:30:45 +00001495 break;
1496 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001497# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001498
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001499#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001500
Eric Andersen3b1a7442003-12-24 20:30:45 +00001501 case R_V850_NONE:
1502 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001503
Eric Andersen3b1a7442003-12-24 20:30:45 +00001504 case R_V850_32:
1505 /* We write two shorts instead of a long because even
1506 32-bit insns only need half-word alignment, but
1507 32-bit data needs to be long-word aligned. */
1508 v += ((unsigned short *)loc)[0];
1509 v += ((unsigned short *)loc)[1] << 16;
1510 ((unsigned short *)loc)[0] = v & 0xffff;
1511 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1512 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001513
Eric Andersen3b1a7442003-12-24 20:30:45 +00001514 case R_V850_22_PCREL:
1515 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001516
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001517#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001518
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001519 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001520 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001521
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001522 case R_X86_64_64:
1523 *loc += v;
1524 break;
1525
1526 case R_X86_64_32:
1527 *(unsigned int *) loc += v;
1528 if (v > 0xffffffff)
1529 {
1530 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1531 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1532 }
1533 break;
1534
1535 case R_X86_64_32S:
1536 *(signed int *) loc += v;
1537 break;
1538
1539 case R_X86_64_16:
1540 *(unsigned short *) loc += v;
1541 break;
1542
1543 case R_X86_64_8:
1544 *(unsigned char *) loc += v;
1545 break;
1546
1547 case R_X86_64_PC32:
1548 *(unsigned int *) loc += v - dot;
1549 break;
1550
1551 case R_X86_64_PC16:
1552 *(unsigned short *) loc += v - dot;
1553 break;
1554
1555 case R_X86_64_PC8:
1556 *(unsigned char *) loc += v - dot;
1557 break;
1558
1559 case R_X86_64_GLOB_DAT:
1560 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001561 *loc = v;
1562 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001563
1564 case R_X86_64_RELATIVE:
1565 *loc += f->baseaddr;
1566 break;
1567
1568 case R_X86_64_GOT32:
1569 case R_X86_64_GOTPCREL:
1570 goto bb_use_got;
1571# if 0
1572 assert(isym != NULL);
1573 if (!isym->gotent.reloc_done)
1574 {
1575 isym->gotent.reloc_done = 1;
1576 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1577 }
1578 /* XXX are these really correct? */
1579 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1580 *(unsigned int *) loc += v + isym->gotent.offset;
1581 else
1582 *loc += isym->gotent.offset;
1583 break;
1584# endif
1585
Mike Frysingerf982d862006-01-04 00:11:26 +00001586#else
1587# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001588#endif
1589
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001590 default:
1591 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1592 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001593 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001594
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001595#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001596
Eric Andersen3b1a7442003-12-24 20:30:45 +00001597bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001598
Eric Andersen3b1a7442003-12-24 20:30:45 +00001599 /* find the plt entry and initialize it if necessary */
1600 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001601
Eric Andersencffd5022002-05-24 06:50:15 +00001602#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001603 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1604 pe = pe->next;
1605 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001606#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001607 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001608#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001609
Eric Andersen3b1a7442003-12-24 20:30:45 +00001610 if (! pe->inited) {
1611 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001612
Eric Andersen3b1a7442003-12-24 20:30:45 +00001613 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001614
1615#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001616 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1617 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001618#endif
1619#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001620 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001621 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001622 ip[2] = 0x7d6903a6; /* mtctr r11 */
1623 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001624#endif
Miles Baderae28b042002-04-01 09:34:25 +00001625#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001626 /* We have to trash a register, so we assume that any control
1627 transfer more than 21-bits away must be a function call
1628 (so we can use a call-clobbered register). */
1629 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1630 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001631#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001632 pe->inited = 1;
1633 }
Eric Andersen21adca72000-12-06 18:18:26 +00001634
Eric Andersen3b1a7442003-12-24 20:30:45 +00001635 /* relative distance to target */
1636 v -= dot;
1637 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001638#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001639 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001640#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001641 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001642#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 /* go via the plt */
1644 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001645
1646#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001648#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001650#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001651 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001652
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001654#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 /* Convert to words. */
1656 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001657
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001659#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001660#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001662#endif
Miles Baderae28b042002-04-01 09:34:25 +00001663#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001664 /* We write two shorts instead of a long because even 32-bit insns
1665 only need half-word alignment, but the 32-bit data write needs
1666 to be long-word aligned. */
1667 ((unsigned short *)loc)[0] =
1668 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1669 | ((v >> 16) & 0x3f); /* offs high part */
1670 ((unsigned short *)loc)[1] =
1671 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001672#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001673 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001674#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001675
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001676#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001677bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001678
Eric Andersen3b1a7442003-12-24 20:30:45 +00001679 assert(isym != NULL);
1680 /* needs an entry in the .got: set it, once */
1681 if (!isym->gotent.inited) {
1682 isym->gotent.inited = 1;
1683 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1684 }
1685 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001686#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001687 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001688#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001689 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001690#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001691 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001692
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001693#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001694 }
1695
1696 return ret;
1697}
1698
Eric Andersencffd5022002-05-24 06:50:15 +00001699
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001700#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001701
1702static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1703 int offset, int size)
1704{
1705 struct arch_list_entry *pe;
1706
1707 for (pe = *list; pe != NULL; pe = pe->next) {
1708 if (pe->addend == rel->r_addend) {
1709 break;
1710 }
1711 }
1712
1713 if (pe == NULL) {
1714 pe = xmalloc(sizeof(struct arch_list_entry));
1715 pe->next = *list;
1716 pe->addend = rel->r_addend;
1717 pe->offset = offset;
1718 pe->inited = 0;
1719 *list = pe;
1720 return size;
1721 }
1722 return 0;
1723}
1724
1725#endif
1726
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001727#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001728
1729static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1730 int offset, int size)
1731{
1732 if (single->allocated == 0) {
1733 single->allocated = 1;
1734 single->offset = offset;
1735 single->inited = 0;
1736 return size;
1737 }
1738 return 0;
1739}
1740
1741#endif
1742
1743#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1744
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001745static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001746 int offset, int size)
1747{
1748 struct obj_section *myrelsec = obj_find_section(f, name);
1749
1750 if (offset == 0) {
1751 offset += size;
1752 }
1753
1754 if (myrelsec) {
1755 obj_extend_section(myrelsec, offset);
1756 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001757 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001758 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001759 assert(myrelsec);
1760 }
1761
1762 return myrelsec;
1763}
1764
1765#endif
1766
1767static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001768{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001769#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001770 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001771 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001772#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001773 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001774#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001775#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001776 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001777#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001778 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001779 ElfW(RelM) *rel, *relend;
1780 ElfW(Sym) *symtab, *extsym;
1781 const char *strtab, *name;
1782 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001783
Eric Andersen21adca72000-12-06 18:18:26 +00001784 for (i = 0; i < f->header.e_shnum; ++i) {
1785 relsec = f->sections[i];
1786 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001787 continue;
1788
Eric Andersen21adca72000-12-06 18:18:26 +00001789 symsec = f->sections[relsec->header.sh_link];
1790 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001791
Eric Andersen21adca72000-12-06 18:18:26 +00001792 rel = (ElfW(RelM) *) relsec->contents;
1793 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1794 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001795 strtab = (const char *) strsec->contents;
1796
1797 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001798 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001799
Eric Andersencffd5022002-05-24 06:50:15 +00001800#if defined(CONFIG_USE_GOT_ENTRIES)
1801 got_allocate = 0;
1802#endif
1803#if defined(CONFIG_USE_PLT_ENTRIES)
1804 plt_allocate = 0;
1805#endif
1806
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001807 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001808#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001809 case R_ARM_PC24:
1810 case R_ARM_PLT32:
1811 plt_allocate = 1;
1812 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001813
Eric Andersen3b1a7442003-12-24 20:30:45 +00001814 case R_ARM_GOTOFF:
1815 case R_ARM_GOTPC:
1816 got_needed = 1;
1817 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001818
Eric Andersen3b1a7442003-12-24 20:30:45 +00001819 case R_ARM_GOT32:
1820 got_allocate = 1;
1821 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001822
Eric Andersen21adca72000-12-06 18:18:26 +00001823#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001824 case R_386_GOTPC:
1825 case R_386_GOTOFF:
1826 got_needed = 1;
1827 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001828
Eric Andersen3b1a7442003-12-24 20:30:45 +00001829 case R_386_GOT32:
1830 got_allocate = 1;
1831 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001832
1833#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001834 case R_PPC_REL24:
1835 plt_allocate = 1;
1836 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001837
1838#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001839 case R_68K_GOT32:
1840 got_allocate = 1;
1841 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001842
Eric Andersen16451a02004-03-19 12:16:18 +00001843#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001844 case R_68K_GOTOFF:
1845 got_needed = 1;
1846 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001847#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001848
1849#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001850 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001851 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001852 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001853
Eric Andersen3b1a7442003-12-24 20:30:45 +00001854 case R_SH_GOTPC:
1855 case R_SH_GOTOFF:
1856 got_needed = 1;
1857 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001858
1859#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001860 case R_V850_22_PCREL:
1861 plt_needed = 1;
1862 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001863
1864#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001865 default:
1866 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001867 }
1868
Eric Andersen21adca72000-12-06 18:18:26 +00001869 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001870 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001871 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001872 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001873 }
1874 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001875#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001876 if (got_allocate) {
1877 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001878 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001879 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001880
1881 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001882 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001883#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001884#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001885 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001886#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001887 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001888 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001889 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001890#else
1891 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001892 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001893 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001894#endif
1895 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001896 }
1897#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001898 }
Miles Baderae28b042002-04-01 09:34:25 +00001899 }
Eric Andersen21adca72000-12-06 18:18:26 +00001900
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001901#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001902 if (got_needed) {
1903 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001904 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001905 }
Eric Andersen21adca72000-12-06 18:18:26 +00001906#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001907
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001908#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001909 if (plt_needed) {
1910 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001911 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001912 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001913#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001914
1915#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001916}
1917
Eric Andersen9f16d612000-06-12 23:11:16 +00001918/*======================================================================*/
1919
1920/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001921static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001922{
1923 unsigned long h = 0;
1924 unsigned long g;
1925 unsigned char ch;
1926
1927 while (n > 0) {
1928 ch = *name++;
1929 h = (h << 4) + ch;
1930 if ((g = (h & 0xf0000000)) != 0) {
1931 h ^= g >> 24;
1932 h &= ~g;
1933 }
1934 n--;
1935 }
1936 return h;
1937}
1938
Eric Andersen044228d2001-07-17 01:12:36 +00001939static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001940{
1941 return obj_elf_hash_n(name, strlen(name));
1942}
1943
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001944#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001945/* String comparison for non-co-versioned kernel and module. */
1946
1947static int ncv_strcmp(const char *a, const char *b)
1948{
1949 size_t alen = strlen(a), blen = strlen(b);
1950
1951 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1952 return strncmp(a, b, alen);
1953 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1954 return strncmp(a, b, blen);
1955 else
1956 return strcmp(a, b);
1957}
1958
1959/* String hashing for non-co-versioned kernel and module. Here
1960 we are simply forced to drop the crc from the hash. */
1961
1962static unsigned long ncv_symbol_hash(const char *str)
1963{
1964 size_t len = strlen(str);
1965 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1966 len -= 10;
1967 return obj_elf_hash_n(str, len);
1968}
1969
Eric Andersen044228d2001-07-17 01:12:36 +00001970static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001971obj_set_symbol_compare(struct obj_file *f,
1972 int (*cmp) (const char *, const char *),
1973 unsigned long (*hash) (const char *))
1974{
1975 if (cmp)
1976 f->symbol_cmp = cmp;
1977 if (hash) {
1978 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1979 int i;
1980
1981 f->symbol_hash = hash;
1982
1983 memcpy(tmptab, f->symtab, sizeof(tmptab));
1984 memset(f->symtab, 0, sizeof(f->symtab));
1985
1986 for (i = 0; i < HASH_BUCKETS; ++i)
1987 for (sym = tmptab[i]; sym; sym = next) {
1988 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1989 next = sym->next;
1990 sym->next = f->symtab[h];
1991 f->symtab[h] = sym;
1992 }
1993 }
1994}
1995
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001996#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001997
Eric Andersen044228d2001-07-17 01:12:36 +00001998static struct obj_symbol *
1999obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00002000 unsigned long symidx, int info,
2001 int secidx, ElfW(Addr) value,
2002 unsigned long size)
2003{
2004 struct obj_symbol *sym;
2005 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002006 int n_type = ELF_ST_TYPE(info);
2007 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002008
2009 for (sym = f->symtab[hash]; sym; sym = sym->next)
2010 if (f->symbol_cmp(sym->name, name) == 0) {
2011 int o_secidx = sym->secidx;
2012 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002013 int o_type = ELF_ST_TYPE(o_info);
2014 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002015
2016 /* A redefinition! Is it legal? */
2017
2018 if (secidx == SHN_UNDEF)
2019 return sym;
2020 else if (o_secidx == SHN_UNDEF)
2021 goto found;
2022 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2023 /* Cope with local and global symbols of the same name
2024 in the same object file, as might have been created
2025 by ld -r. The only reason locals are now seen at this
2026 level at all is so that we can do semi-sensible things
2027 with parameters. */
2028
2029 struct obj_symbol *nsym, **p;
2030
2031 nsym = arch_new_symbol();
2032 nsym->next = sym->next;
2033 nsym->ksymidx = -1;
2034
2035 /* Excise the old (local) symbol from the hash chain. */
2036 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2037 continue;
2038 *p = sym = nsym;
2039 goto found;
2040 } else if (n_binding == STB_LOCAL) {
2041 /* Another symbol of the same name has already been defined.
2042 Just add this to the local table. */
2043 sym = arch_new_symbol();
2044 sym->next = NULL;
2045 sym->ksymidx = -1;
2046 f->local_symtab[symidx] = sym;
2047 goto found;
2048 } else if (n_binding == STB_WEAK)
2049 return sym;
2050 else if (o_binding == STB_WEAK)
2051 goto found;
2052 /* Don't unify COMMON symbols with object types the programmer
2053 doesn't expect. */
2054 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002055 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002056 return sym;
2057 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002058 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002059 goto found;
2060 else {
2061 /* Don't report an error if the symbol is coming from
2062 the kernel or some external module. */
2063 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002064 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002065 return sym;
2066 }
2067 }
2068
2069 /* Completely new symbol. */
2070 sym = arch_new_symbol();
2071 sym->next = f->symtab[hash];
2072 f->symtab[hash] = sym;
2073 sym->ksymidx = -1;
2074
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002075 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002076 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002077 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002078 name, (long) symidx, (long) f->local_symtab_size);
2079 else
2080 f->local_symtab[symidx] = sym;
2081 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002082
Eric Andersen3b1a7442003-12-24 20:30:45 +00002083found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002084 sym->name = name;
2085 sym->value = value;
2086 sym->size = size;
2087 sym->secidx = secidx;
2088 sym->info = info;
2089
2090 return sym;
2091}
2092
Eric Andersen044228d2001-07-17 01:12:36 +00002093static struct obj_symbol *
2094obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002095{
2096 struct obj_symbol *sym;
2097 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2098
2099 for (sym = f->symtab[hash]; sym; sym = sym->next)
2100 if (f->symbol_cmp(sym->name, name) == 0)
2101 return sym;
2102
2103 return NULL;
2104}
2105
Eric Andersen044228d2001-07-17 01:12:36 +00002106static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002107 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2108{
2109 if (sym) {
2110 if (sym->secidx >= SHN_LORESERVE)
2111 return sym->value;
2112
2113 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2114 } else {
2115 /* As a special case, a NULL sym has value zero. */
2116 return 0;
2117 }
2118}
2119
Eric Andersen044228d2001-07-17 01:12:36 +00002120static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002121{
2122 int i, n = f->header.e_shnum;
2123
2124 for (i = 0; i < n; ++i)
2125 if (strcmp(f->sections[i]->name, name) == 0)
2126 return f->sections[i];
2127
2128 return NULL;
2129}
2130
2131static int obj_load_order_prio(struct obj_section *a)
2132{
2133 unsigned long af, ac;
2134
2135 af = a->header.sh_flags;
2136
2137 ac = 0;
2138 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002139 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002140 ac |= 32;
2141 if (af & SHF_ALLOC)
2142 ac |= 16;
2143 if (!(af & SHF_WRITE))
2144 ac |= 8;
2145 if (af & SHF_EXECINSTR)
2146 ac |= 4;
2147 if (a->header.sh_type != SHT_NOBITS)
2148 ac |= 2;
2149
2150 return ac;
2151}
2152
Eric Andersen044228d2001-07-17 01:12:36 +00002153static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002154obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2155{
2156 struct obj_section **p;
2157 int prio = obj_load_order_prio(sec);
2158 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2159 if (obj_load_order_prio(*p) < prio)
2160 break;
2161 sec->load_next = *p;
2162 *p = sec;
2163}
2164
Eric Andersen044228d2001-07-17 01:12:36 +00002165static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002166 const char *name,
2167 unsigned long align,
2168 unsigned long size)
2169{
2170 int newidx = f->header.e_shnum++;
2171 struct obj_section *sec;
2172
2173 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2174 f->sections[newidx] = sec = arch_new_section();
2175
2176 memset(sec, 0, sizeof(*sec));
2177 sec->header.sh_type = SHT_PROGBITS;
2178 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2179 sec->header.sh_size = size;
2180 sec->header.sh_addralign = align;
2181 sec->name = name;
2182 sec->idx = newidx;
2183 if (size)
2184 sec->contents = xmalloc(size);
2185
2186 obj_insert_section_load_order(f, sec);
2187
2188 return sec;
2189}
2190
Eric Andersen044228d2001-07-17 01:12:36 +00002191static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002192 const char *name,
2193 unsigned long align,
2194 unsigned long size)
2195{
2196 int newidx = f->header.e_shnum++;
2197 struct obj_section *sec;
2198
2199 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2200 f->sections[newidx] = sec = arch_new_section();
2201
2202 memset(sec, 0, sizeof(*sec));
2203 sec->header.sh_type = SHT_PROGBITS;
2204 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2205 sec->header.sh_size = size;
2206 sec->header.sh_addralign = align;
2207 sec->name = name;
2208 sec->idx = newidx;
2209 if (size)
2210 sec->contents = xmalloc(size);
2211
2212 sec->load_next = f->load_order;
2213 f->load_order = sec;
2214 if (f->load_order_search_start == &f->load_order)
2215 f->load_order_search_start = &sec->load_next;
2216
2217 return sec;
2218}
2219
Eric Andersen044228d2001-07-17 01:12:36 +00002220static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002221{
2222 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002223 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002224 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2225 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002226 return sec->contents + oldsize;
2227}
2228
2229
Eric Andersen9f16d612000-06-12 23:11:16 +00002230/* Conditionally add the symbols from the given symbol set to the
2231 new module. */
2232
2233static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002234add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002235 int idx, struct new_module_symbol *syms, size_t nsyms)
2236{
2237 struct new_module_symbol *s;
2238 size_t i;
2239 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002240#ifdef SYMBOL_PREFIX
2241 char *name_buf = 0;
2242 size_t name_alloced_size = 0;
2243#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002244#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2245 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002246
Glenn L McGrath759515c2003-08-30 06:00:33 +00002247 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002248#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002249 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002250 /* Only add symbols that are already marked external.
2251 If we override locals we may cause problems for
2252 argument initialization. We will also create a false
2253 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002254 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002255 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002256
Glenn L McGrath759515c2003-08-30 06:00:33 +00002257 /* GPL licensed modules can use symbols exported with
2258 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2259 * exported names. Non-GPL modules never see any GPLONLY_
2260 * symbols so they cannot fudge it by adding the prefix on
2261 * their references.
2262 */
2263 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002264#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002265 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002266 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002267 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002268#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002269 continue;
2270 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002271 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002272
Miles Baderae28b042002-04-01 09:34:25 +00002273#ifdef SYMBOL_PREFIX
2274 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2275 kernel exports `C names', but module object files
2276 reference `linker names'). */
2277 size_t extra = sizeof SYMBOL_PREFIX;
2278 size_t name_size = strlen (name) + extra;
2279 if (name_size > name_alloced_size) {
2280 name_alloced_size = name_size * 2;
2281 name_buf = alloca (name_alloced_size);
2282 }
2283 strcpy (name_buf, SYMBOL_PREFIX);
2284 strcpy (name_buf + extra - 1, name);
2285 name = name_buf;
2286#endif /* SYMBOL_PREFIX */
2287
2288 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002289 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002290#ifdef SYMBOL_PREFIX
2291 /* Put NAME_BUF into more permanent storage. */
2292 name = xmalloc (name_size);
2293 strcpy (name, name_buf);
2294#endif
2295 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002296 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002297 STT_NOTYPE),
2298 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002299 /* Did our symbol just get installed? If so, mark the
2300 module as "used". */
2301 if (sym->secidx == idx)
2302 used = 1;
2303 }
2304 }
2305
2306 return used;
2307}
2308
2309static void add_kernel_symbols(struct obj_file *f)
2310{
2311 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002312 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002313
2314 /* Add module symbols first. */
2315
2316 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2317 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002318 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2319 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002320
2321 n_ext_modules_used = nused;
2322
2323 /* And finally the symbols from the kernel proper. */
2324
2325 if (nksyms)
2326 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2327}
2328
2329static char *get_modinfo_value(struct obj_file *f, const char *key)
2330{
2331 struct obj_section *sec;
2332 char *p, *v, *n, *ep;
2333 size_t klen = strlen(key);
2334
2335 sec = obj_find_section(f, ".modinfo");
2336 if (sec == NULL)
2337 return NULL;
2338 p = sec->contents;
2339 ep = p + sec->header.sh_size;
2340 while (p < ep) {
2341 v = strchr(p, '=');
2342 n = strchr(p, '\0');
2343 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002344 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002345 return v + 1;
2346 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002347 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002348 return n;
2349 }
2350 p = n + 1;
2351 }
2352
2353 return NULL;
2354}
2355
2356
2357/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002358/* Functions relating to module loading after 2.1.18. */
2359
2360static int
2361new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2362{
2363 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002364 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002365 struct obj_symbol *sym;
2366 char *contents, *loc;
2367 int min, max, n;
2368
2369 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002370 if ((q = strchr(p, '=')) == NULL) {
2371 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002372 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002373 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002374
2375 key = alloca(q - p + 6);
2376 memcpy(key, "parm_", 5);
2377 memcpy(key + 5, p, q - p);
2378 key[q - p + 5] = 0;
2379
2380 p = get_modinfo_value(f, key);
2381 key += 5;
2382 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002383 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002384 return 0;
2385 }
2386
Miles Baderae28b042002-04-01 09:34:25 +00002387#ifdef SYMBOL_PREFIX
2388 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2389 strcpy (sym_name, SYMBOL_PREFIX);
2390 strcat (sym_name, key);
2391#else
2392 sym_name = key;
2393#endif
2394 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002395
2396 /* Also check that the parameter was not resolved from the kernel. */
2397 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002398 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 return 0;
2400 }
2401
2402 if (isdigit(*p)) {
2403 min = strtoul(p, &p, 10);
2404 if (*p == '-')
2405 max = strtoul(p + 1, &p, 10);
2406 else
2407 max = min;
2408 } else
2409 min = max = 1;
2410
2411 contents = f->sections[sym->secidx]->contents;
2412 loc = contents + sym->value;
2413 n = (*++q != '\0');
2414
2415 while (1) {
2416 if ((*p == 's') || (*p == 'c')) {
2417 char *str;
2418
2419 /* Do C quoting if we begin with a ", else slurp the lot. */
2420 if (*q == '"') {
2421 char *r;
2422
2423 str = alloca(strlen(q));
2424 for (r = str, q++; *q != '"'; ++q, ++r) {
2425 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002426 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002427 key);
2428 return 0;
2429 } else if (*q == '\\')
2430 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002431 case 'a':
2432 *r = '\a';
2433 break;
2434 case 'b':
2435 *r = '\b';
2436 break;
2437 case 'e':
2438 *r = '\033';
2439 break;
2440 case 'f':
2441 *r = '\f';
2442 break;
2443 case 'n':
2444 *r = '\n';
2445 break;
2446 case 'r':
2447 *r = '\r';
2448 break;
2449 case 't':
2450 *r = '\t';
2451 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002452
Eric Andersen3b1a7442003-12-24 20:30:45 +00002453 case '0':
2454 case '1':
2455 case '2':
2456 case '3':
2457 case '4':
2458 case '5':
2459 case '6':
2460 case '7':
2461 {
2462 int c = *q - '0';
2463 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002464 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002465 if (q[1] >= '0' && q[1] <= '7')
2466 c = (c * 8) + *++q - '0';
2467 }
2468 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002469 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002470 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002471
Eric Andersen3b1a7442003-12-24 20:30:45 +00002472 default:
2473 *r = *q;
2474 break;
2475 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002476 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002477 }
2478 *r = '\0';
2479 ++q;
2480 } else {
2481 char *r;
2482
2483 /* In this case, the string is not quoted. We will break
2484 it using the coma (like for ints). If the user wants to
2485 include comas in a string, he just has to quote it */
2486
2487 /* Search the next coma */
2488 r = strchr(q, ',');
2489
2490 /* Found ? */
2491 if (r != (char *) NULL) {
2492 /* Recopy the current field */
2493 str = alloca(r - q + 1);
2494 memcpy(str, q, r - q);
2495
Eric Andersenaff114c2004-04-14 17:51:38 +00002496 /* I don't know if it is useful, as the previous case
2497 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002498 str[r - q] = '\0';
2499
2500 /* Keep next fields */
2501 q = r;
2502 } else {
2503 /* last string */
2504 str = q;
2505 q = "";
2506 }
2507 }
2508
2509 if (*p == 's') {
2510 /* Normal string */
2511 obj_string_patch(f, sym->secidx, loc - contents, str);
2512 loc += tgt_sizeof_char_p;
2513 } else {
2514 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002515 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002516
2517 /* Get the size of each member */
2518 /* Probably we should do that outside the loop ? */
2519 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002520 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002521 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002522 return 0;
2523 }
2524 charssize = strtoul(p + 1, (char **) NULL, 10);
2525
2526 /* Check length */
2527 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002528 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002529 charssize - 1);
2530 return 0;
2531 }
2532
2533 /* Copy to location */
2534 strcpy((char *) loc, str);
2535 loc += charssize;
2536 }
2537 } else {
2538 long v = strtoul(q, &q, 0);
2539 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002540 case 'b':
2541 *loc++ = v;
2542 break;
2543 case 'h':
2544 *(short *) loc = v;
2545 loc += tgt_sizeof_short;
2546 break;
2547 case 'i':
2548 *(int *) loc = v;
2549 loc += tgt_sizeof_int;
2550 break;
2551 case 'l':
2552 *(long *) loc = v;
2553 loc += tgt_sizeof_long;
2554 break;
2555
2556 default:
2557 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2558 return 0;
2559 }
2560 }
2561
2562retry_end_of_value:
2563 switch (*q) {
2564 case '\0':
2565 goto end_of_arg;
2566
2567 case ' ':
2568 case '\t':
2569 case '\n':
2570 case '\r':
2571 ++q;
2572 goto retry_end_of_value;
2573
2574 case ',':
2575 if (++n > max) {
2576 bb_error_msg("too many values for %s (max %d)", key, max);
2577 return 0;
2578 }
2579 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002580 break;
2581
2582 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002583 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002584 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002585 }
2586 }
2587
Eric Andersen3b1a7442003-12-24 20:30:45 +00002588end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002589 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002590 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002591 return 0;
2592 }
2593
2594 argc--, argv++;
2595 }
2596
2597 return 1;
2598}
2599
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002600#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002601static int new_is_module_checksummed(struct obj_file *f)
2602{
2603 const char *p = get_modinfo_value(f, "using_checksums");
2604 if (p)
2605 return atoi(p);
2606 else
2607 return 0;
2608}
2609
2610/* Get the module's kernel version in the canonical integer form. */
2611
2612static int
2613new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2614{
2615 char *p, *q;
2616 int a, b, c;
2617
2618 p = get_modinfo_value(f, "kernel_version");
2619 if (p == NULL)
2620 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002621 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002622
2623 a = strtoul(p, &p, 10);
2624 if (*p != '.')
2625 return -1;
2626 b = strtoul(p + 1, &p, 10);
2627 if (*p != '.')
2628 return -1;
2629 c = strtoul(p + 1, &q, 10);
2630 if (p + 1 == q)
2631 return -1;
2632
2633 return a << 16 | b << 8 | c;
2634}
2635
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002636#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002637
2638
Eric Andersen9f16d612000-06-12 23:11:16 +00002639/* Fetch the loaded modules, and all currently exported symbols. */
2640
2641static int new_get_kernel_symbols(void)
2642{
2643 char *module_names, *mn;
2644 struct external_module *modules, *m;
2645 struct new_module_symbol *syms, *s;
2646 size_t ret, bufsize, nmod, nsyms, i, j;
2647
2648 /* Collect the loaded modules. */
2649
2650 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002651retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002652 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002653 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002654 module_names = xrealloc(module_names, bufsize = ret);
2655 goto retry_modules_load;
2656 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002657 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002658 return 0;
2659 }
2660
2661 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002662
2663 /* Collect the modules' symbols. */
2664
Mark Whitley94fd4802001-03-12 23:08:34 +00002665 if (nmod){
2666 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2667 memset(modules, 0, nmod * sizeof(*modules));
2668 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002669 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002670 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002671
Mark Whitley94fd4802001-03-12 23:08:34 +00002672 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2673 if (errno == ENOENT) {
2674 /* The module was removed out from underneath us. */
2675 continue;
2676 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002677 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002678 return 0;
2679 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002680
Mark Whitley94fd4802001-03-12 23:08:34 +00002681 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002682retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002683 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2684 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002685 case ENOSPC:
2686 syms = xrealloc(syms, bufsize = ret);
2687 goto retry_mod_sym_load;
2688 case ENOENT:
2689 /* The module was removed out from underneath us. */
2690 continue;
2691 default:
2692 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2693 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002694 }
2695 }
2696 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002697
Mark Whitley94fd4802001-03-12 23:08:34 +00002698 m->name = mn;
2699 m->addr = info.addr;
2700 m->nsyms = nsyms;
2701 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002702
Mark Whitley94fd4802001-03-12 23:08:34 +00002703 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2704 s->name += (unsigned long) syms;
2705 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002706 }
2707 }
2708
2709 /* Collect the kernel's symbols. */
2710
2711 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002712retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002713 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002714 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002715 syms = xrealloc(syms, bufsize = ret);
2716 goto retry_kern_sym_load;
2717 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002718 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002719 return 0;
2720 }
2721 nksyms = nsyms = ret;
2722 ksyms = syms;
2723
2724 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2725 s->name += (unsigned long) syms;
2726 }
2727 return 1;
2728}
2729
2730
2731/* Return the kernel symbol checksum version, or zero if not used. */
2732
2733static int new_is_kernel_checksummed(void)
2734{
2735 struct new_module_symbol *s;
2736 size_t i;
2737
2738 /* Using_Versions is not the first symbol, but it should be in there. */
2739
2740 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2741 if (strcmp((char *) s->name, "Using_Versions") == 0)
2742 return s->value;
2743
2744 return 0;
2745}
2746
2747
2748static int new_create_this_module(struct obj_file *f, const char *m_name)
2749{
2750 struct obj_section *sec;
2751
2752 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002753 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002754 memset(sec->contents, 0, sizeof(struct new_module));
2755
Miles Baderae28b042002-04-01 09:34:25 +00002756 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002757 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002758 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002759
2760 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002761 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002762
2763 return 1;
2764}
2765
Eric Andersen889dd202003-01-23 04:48:34 +00002766#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2767/* add an entry to the __ksymtab section, creating it if necessary */
2768static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2769{
2770 struct obj_section *sec;
2771 ElfW(Addr) ofs;
2772
2773 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2774 * If __ksymtab is defined but not marked alloc, x out the first character
2775 * (no obj_delete routine) and create a new __ksymtab with the correct
2776 * characteristics.
2777 */
2778 sec = obj_find_section(f, "__ksymtab");
2779 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2780 *((char *)(sec->name)) = 'x'; /* override const */
2781 sec = NULL;
2782 }
2783 if (!sec)
2784 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002785 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002786 if (!sec)
2787 return;
2788 sec->header.sh_flags |= SHF_ALLOC;
2789 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002790 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002791 ofs = sec->header.sh_size;
2792 obj_symbol_patch(f, sec->idx, ofs, sym);
2793 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2794 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2795}
2796#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002797
2798static int new_create_module_ksymtab(struct obj_file *f)
2799{
2800 struct obj_section *sec;
2801 int i;
2802
2803 /* We must always add the module references. */
2804
2805 if (n_ext_modules_used) {
2806 struct new_module_ref *dep;
2807 struct obj_symbol *tm;
2808
2809 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002810 (sizeof(struct new_module_ref)
2811 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002812 if (!sec)
2813 return 0;
2814
Miles Baderae28b042002-04-01 09:34:25 +00002815 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002816 dep = (struct new_module_ref *) sec->contents;
2817 for (i = 0; i < n_ext_modules; ++i)
2818 if (ext_modules[i].used) {
2819 dep->dep = ext_modules[i].addr;
2820 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002821 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002822 dep->next_ref = 0;
2823 ++dep;
2824 }
2825 }
2826
2827 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2828 size_t nsyms;
2829 int *loaded;
2830
2831 sec =
2832 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002833 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002834
2835 /* We don't want to export symbols residing in sections that
2836 aren't loaded. There are a number of these created so that
2837 we make sure certain module options don't appear twice. */
2838
2839 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2840 while (--i >= 0)
2841 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2842
2843 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2844 struct obj_symbol *sym;
2845 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002846 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002847 && sym->secidx <= SHN_HIRESERVE
2848 && (sym->secidx >= SHN_LORESERVE
2849 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002850 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2851
2852 obj_symbol_patch(f, sec->idx, ofs, sym);
2853 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002854 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002855
2856 nsyms++;
2857 }
2858 }
2859
2860 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2861 }
2862
2863 return 1;
2864}
2865
2866
2867static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002868new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002869{
2870 struct new_module *module;
2871 struct obj_section *sec;
2872 void *image;
2873 int ret;
2874 tgt_long m_addr;
2875
2876 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002877 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002878 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002879 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002880 module = (struct new_module *) sec->contents;
2881 m_addr = sec->header.sh_addr;
2882
2883 module->size_of_struct = sizeof(*module);
2884 module->size = m_size;
2885 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2886
2887 sec = obj_find_section(f, "__ksymtab");
2888 if (sec && sec->header.sh_size) {
2889 module->syms = sec->header.sh_addr;
2890 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2891 }
2892
2893 if (n_ext_modules_used) {
2894 sec = obj_find_section(f, ".kmodtab");
2895 module->deps = sec->header.sh_addr;
2896 module->ndeps = n_ext_modules_used;
2897 }
2898
2899 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002900 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002901 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002902 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002903
2904 sec = obj_find_section(f, "__ex_table");
2905 if (sec) {
2906 module->ex_table_start = sec->header.sh_addr;
2907 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2908 }
2909
2910 sec = obj_find_section(f, ".text.init");
2911 if (sec) {
2912 module->runsize = sec->header.sh_addr - m_addr;
2913 }
2914 sec = obj_find_section(f, ".data.init");
2915 if (sec) {
2916 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002917 module->runsize > sec->header.sh_addr - m_addr)
2918 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002919 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002920 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2921 if (sec && sec->header.sh_size) {
2922 module->archdata_start = (void*)sec->header.sh_addr;
2923 module->archdata_end = module->archdata_start + sec->header.sh_size;
2924 }
2925 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2926 if (sec && sec->header.sh_size) {
2927 module->kallsyms_start = (void*)sec->header.sh_addr;
2928 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2929 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002930
Eric Andersen9f16d612000-06-12 23:11:16 +00002931 /* Whew! All of the initialization is complete. Collect the final
2932 module image and give it to the kernel. */
2933
2934 image = xmalloc(m_size);
2935 obj_create_image(f, image);
2936
Eric Andersencb3b9b12004-06-22 11:50:52 +00002937 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002938 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002939 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002940
2941 free(image);
2942
2943 return ret == 0;
2944}
2945
Eric Andersen9f16d612000-06-12 23:11:16 +00002946
2947/*======================================================================*/
2948
Eric Andersen044228d2001-07-17 01:12:36 +00002949static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002950obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2951 const char *string)
2952{
2953 struct obj_string_patch *p;
2954 struct obj_section *strsec;
2955 size_t len = strlen(string) + 1;
2956 char *loc;
2957
2958 p = xmalloc(sizeof(*p));
2959 p->next = f->string_patches;
2960 p->reloc_secidx = secidx;
2961 p->reloc_offset = offset;
2962 f->string_patches = p;
2963
2964 strsec = obj_find_section(f, ".kstrtab");
2965 if (strsec == NULL) {
2966 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2967 p->string_offset = 0;
2968 loc = strsec->contents;
2969 } else {
2970 p->string_offset = strsec->header.sh_size;
2971 loc = obj_extend_section(strsec, len);
2972 }
2973 memcpy(loc, string, len);
2974
2975 return 1;
2976}
2977
Eric Andersen044228d2001-07-17 01:12:36 +00002978static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002979obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2980 struct obj_symbol *sym)
2981{
2982 struct obj_symbol_patch *p;
2983
2984 p = xmalloc(sizeof(*p));
2985 p->next = f->symbol_patches;
2986 p->reloc_secidx = secidx;
2987 p->reloc_offset = offset;
2988 p->sym = sym;
2989 f->symbol_patches = p;
2990
2991 return 1;
2992}
2993
Eric Andersen044228d2001-07-17 01:12:36 +00002994static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002995{
2996 unsigned long i;
2997 int ret = 1;
2998
2999 for (i = 0; i < HASH_BUCKETS; ++i) {
3000 struct obj_symbol *sym;
3001 for (sym = f->symtab[i]; sym; sym = sym->next)
3002 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003003 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003004 sym->secidx = SHN_ABS;
3005 sym->value = 0;
3006 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003007 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003008 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003009 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003010 ret = 0;
3011 }
3012 }
3013 }
3014
3015 return ret;
3016}
3017
Eric Andersen044228d2001-07-17 01:12:36 +00003018static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003019{
3020 struct common_entry {
3021 struct common_entry *next;
3022 struct obj_symbol *sym;
3023 } *common_head = NULL;
3024
3025 unsigned long i;
3026
3027 for (i = 0; i < HASH_BUCKETS; ++i) {
3028 struct obj_symbol *sym;
3029 for (sym = f->symtab[i]; sym; sym = sym->next)
3030 if (sym->secidx == SHN_COMMON) {
3031 /* Collect all COMMON symbols and sort them by size so as to
3032 minimize space wasted by alignment requirements. */
3033 {
3034 struct common_entry **p, *n;
3035 for (p = &common_head; *p; p = &(*p)->next)
3036 if (sym->size <= (*p)->sym->size)
3037 break;
3038
3039 n = alloca(sizeof(*n));
3040 n->next = *p;
3041 n->sym = sym;
3042 *p = n;
3043 }
3044 }
3045 }
3046
3047 for (i = 1; i < f->local_symtab_size; ++i) {
3048 struct obj_symbol *sym = f->local_symtab[i];
3049 if (sym && sym->secidx == SHN_COMMON) {
3050 struct common_entry **p, *n;
3051 for (p = &common_head; *p; p = &(*p)->next)
3052 if (sym == (*p)->sym)
3053 break;
3054 else if (sym->size < (*p)->sym->size) {
3055 n = alloca(sizeof(*n));
3056 n->next = *p;
3057 n->sym = sym;
3058 *p = n;
3059 break;
3060 }
3061 }
3062 }
3063
3064 if (common_head) {
3065 /* Find the bss section. */
3066 for (i = 0; i < f->header.e_shnum; ++i)
3067 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3068 break;
3069
3070 /* If for some reason there hadn't been one, create one. */
3071 if (i == f->header.e_shnum) {
3072 struct obj_section *sec;
3073
3074 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3075 f->sections[i] = sec = arch_new_section();
3076 f->header.e_shnum = i + 1;
3077
3078 memset(sec, 0, sizeof(*sec));
3079 sec->header.sh_type = SHT_PROGBITS;
3080 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3081 sec->name = ".bss";
3082 sec->idx = i;
3083 }
3084
3085 /* Allocate the COMMONS. */
3086 {
3087 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3088 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3089 struct common_entry *c;
3090
3091 for (c = common_head; c; c = c->next) {
3092 ElfW(Addr) align = c->sym->value;
3093
3094 if (align > max_align)
3095 max_align = align;
3096 if (bss_size & (align - 1))
3097 bss_size = (bss_size | (align - 1)) + 1;
3098
3099 c->sym->secidx = i;
3100 c->sym->value = bss_size;
3101
3102 bss_size += c->sym->size;
3103 }
3104
3105 f->sections[i]->header.sh_size = bss_size;
3106 f->sections[i]->header.sh_addralign = max_align;
3107 }
3108 }
3109
3110 /* For the sake of patch relocation and parameter initialization,
3111 allocate zeroed data for NOBITS sections now. Note that after
3112 this we cannot assume NOBITS are really empty. */
3113 for (i = 0; i < f->header.e_shnum; ++i) {
3114 struct obj_section *s = f->sections[i];
3115 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003116 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003117 s->contents = memset(xmalloc(s->header.sh_size),
3118 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003119 else
3120 s->contents = NULL;
3121
Eric Andersen9f16d612000-06-12 23:11:16 +00003122 s->header.sh_type = SHT_PROGBITS;
3123 }
3124 }
3125}
3126
Eric Andersen044228d2001-07-17 01:12:36 +00003127static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003128{
3129 unsigned long dot = 0;
3130 struct obj_section *sec;
3131
3132 /* Finalize the positions of the sections relative to one another. */
3133
3134 for (sec = f->load_order; sec; sec = sec->load_next) {
3135 ElfW(Addr) align;
3136
3137 align = sec->header.sh_addralign;
3138 if (align && (dot & (align - 1)))
3139 dot = (dot | (align - 1)) + 1;
3140
3141 sec->header.sh_addr = dot;
3142 dot += sec->header.sh_size;
3143 }
3144
3145 return dot;
3146}
3147
Eric Andersen044228d2001-07-17 01:12:36 +00003148static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003149{
3150 int i, n = f->header.e_shnum;
3151 int ret = 1;
3152
3153 /* Finalize the addresses of the sections. */
3154
3155 f->baseaddr = base;
3156 for (i = 0; i < n; ++i)
3157 f->sections[i]->header.sh_addr += base;
3158
3159 /* And iterate over all of the relocations. */
3160
3161 for (i = 0; i < n; ++i) {
3162 struct obj_section *relsec, *symsec, *targsec, *strsec;
3163 ElfW(RelM) * rel, *relend;
3164 ElfW(Sym) * symtab;
3165 const char *strtab;
3166
3167 relsec = f->sections[i];
3168 if (relsec->header.sh_type != SHT_RELM)
3169 continue;
3170
3171 symsec = f->sections[relsec->header.sh_link];
3172 targsec = f->sections[relsec->header.sh_info];
3173 strsec = f->sections[symsec->header.sh_link];
3174
3175 rel = (ElfW(RelM) *) relsec->contents;
3176 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3177 symtab = (ElfW(Sym) *) symsec->contents;
3178 strtab = (const char *) strsec->contents;
3179
3180 for (; rel < relend; ++rel) {
3181 ElfW(Addr) value = 0;
3182 struct obj_symbol *intsym = NULL;
3183 unsigned long symndx;
3184 ElfW(Sym) * extsym = 0;
3185 const char *errmsg;
3186
3187 /* Attempt to find a value to use for this relocation. */
3188
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003189 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003190 if (symndx) {
3191 /* Note we've already checked for undefined symbols. */
3192
3193 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003194 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003195 /* Local symbols we look up in the local table to be sure
3196 we get the one that is really intended. */
3197 intsym = f->local_symtab[symndx];
3198 } else {
3199 /* Others we look up in the hash table. */
3200 const char *name;
3201 if (extsym->st_name)
3202 name = strtab + extsym->st_name;
3203 else
3204 name = f->sections[extsym->st_shndx]->name;
3205 intsym = obj_find_symbol(f, name);
3206 }
3207
3208 value = obj_symbol_final_value(f, intsym);
3209 intsym->referenced = 1;
3210 }
3211#if SHT_RELM == SHT_RELA
3212#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3213 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3214 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003215 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003216#endif
3217 value += rel->r_addend;
3218#endif
3219
3220 /* Do it! */
3221 switch (arch_apply_relocation
3222 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003223 case obj_reloc_ok:
3224 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003225
Eric Andersen3b1a7442003-12-24 20:30:45 +00003226 case obj_reloc_overflow:
3227 errmsg = "Relocation overflow";
3228 goto bad_reloc;
3229 case obj_reloc_dangerous:
3230 errmsg = "Dangerous relocation";
3231 goto bad_reloc;
3232 case obj_reloc_unhandled:
3233 errmsg = "Unhandled relocation";
3234bad_reloc:
3235 if (extsym) {
3236 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003237 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003238 strtab + extsym->st_name);
3239 } else {
3240 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003241 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003242 }
3243 ret = 0;
3244 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003245 }
3246 }
3247 }
3248
3249 /* Finally, take care of the patches. */
3250
3251 if (f->string_patches) {
3252 struct obj_string_patch *p;
3253 struct obj_section *strsec;
3254 ElfW(Addr) strsec_base;
3255 strsec = obj_find_section(f, ".kstrtab");
3256 strsec_base = strsec->header.sh_addr;
3257
3258 for (p = f->string_patches; p; p = p->next) {
3259 struct obj_section *targsec = f->sections[p->reloc_secidx];
3260 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3261 = strsec_base + p->string_offset;
3262 }
3263 }
3264
3265 if (f->symbol_patches) {
3266 struct obj_symbol_patch *p;
3267
3268 for (p = f->symbol_patches; p; p = p->next) {
3269 struct obj_section *targsec = f->sections[p->reloc_secidx];
3270 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3271 = obj_symbol_final_value(f, p->sym);
3272 }
3273 }
3274
3275 return ret;
3276}
3277
Eric Andersen044228d2001-07-17 01:12:36 +00003278static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003279{
3280 struct obj_section *sec;
3281 ElfW(Addr) base = f->baseaddr;
3282
3283 for (sec = f->load_order; sec; sec = sec->load_next) {
3284 char *secimg;
3285
Eric Andersen2bf658d2001-02-24 20:01:53 +00003286 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003287 continue;
3288
3289 secimg = image + (sec->header.sh_addr - base);
3290
3291 /* Note that we allocated data for NOBITS sections earlier. */
3292 memcpy(secimg, sec->contents, sec->header.sh_size);
3293 }
3294
3295 return 1;
3296}
3297
3298/*======================================================================*/
3299
Eric Andersen044228d2001-07-17 01:12:36 +00003300static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003301{
3302 struct obj_file *f;
3303 ElfW(Shdr) * section_headers;
3304 int shnum, i;
3305 char *shstrtab;
3306
3307 /* Read the file header. */
3308
3309 f = arch_new_file();
3310 memset(f, 0, sizeof(*f));
3311 f->symbol_cmp = strcmp;
3312 f->symbol_hash = obj_elf_hash;
3313 f->load_order_search_start = &f->load_order;
3314
3315 fseek(fp, 0, SEEK_SET);
3316 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003317 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003318 return NULL;
3319 }
3320
3321 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003322 || f->header.e_ident[EI_MAG1] != ELFMAG1
3323 || f->header.e_ident[EI_MAG2] != ELFMAG2
3324 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003325 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 return NULL;
3327 }
3328 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003329 || f->header.e_ident[EI_DATA] != ELFDATAM
3330 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3331 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003332 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 return NULL;
3334 }
3335 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003336 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003337 return NULL;
3338 }
3339
3340 /* Read the section headers. */
3341
3342 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003343 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003344 (unsigned long) f->header.e_shentsize,
3345 (unsigned long) sizeof(ElfW(Shdr)));
3346 return NULL;
3347 }
3348
3349 shnum = f->header.e_shnum;
3350 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3351 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3352
3353 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3354 fseek(fp, f->header.e_shoff, SEEK_SET);
3355 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003356 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 return NULL;
3358 }
3359
3360 /* Read the section data. */
3361
3362 for (i = 0; i < shnum; ++i) {
3363 struct obj_section *sec;
3364
3365 f->sections[i] = sec = arch_new_section();
3366 memset(sec, 0, sizeof(*sec));
3367
3368 sec->header = section_headers[i];
3369 sec->idx = i;
3370
Eric Andersen2bf658d2001-02-24 20:01:53 +00003371 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003372 case SHT_NULL:
3373 case SHT_NOTE:
3374 case SHT_NOBITS:
3375 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003376 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003377
3378 case SHT_PROGBITS:
3379#if LOADBITS
3380 if (!loadprogbits) {
3381 sec->contents = NULL;
3382 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003383 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003384#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003385 case SHT_SYMTAB:
3386 case SHT_STRTAB:
3387 case SHT_RELM:
3388 if (sec->header.sh_size > 0) {
3389 sec->contents = xmalloc(sec->header.sh_size);
3390 fseek(fp, sec->header.sh_offset, SEEK_SET);
3391 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3392 bb_perror_msg("error reading ELF section data");
3393 return NULL;
3394 }
3395 } else {
3396 sec->contents = NULL;
3397 }
3398 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003399
3400#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003401 case SHT_RELA:
3402 bb_error_msg("RELA relocations not supported on this architecture");
3403 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003404#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003405 case SHT_REL:
3406 bb_error_msg("REL relocations not supported on this architecture");
3407 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003408#endif
3409
Eric Andersen3b1a7442003-12-24 20:30:45 +00003410 default:
3411 if (sec->header.sh_type >= SHT_LOPROC) {
3412 /* Assume processor specific section types are debug
3413 info and can safely be ignored. If this is ever not
3414 the case (Hello MIPS?), don't put ifdefs here but
3415 create an arch_load_proc_section(). */
3416 break;
3417 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003418
Eric Andersen3b1a7442003-12-24 20:30:45 +00003419 bb_error_msg("can't handle sections of type %ld",
3420 (long) sec->header.sh_type);
3421 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003422 }
3423 }
3424
3425 /* Do what sort of interpretation as needed by each section. */
3426
3427 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3428
3429 for (i = 0; i < shnum; ++i) {
3430 struct obj_section *sec = f->sections[i];
3431 sec->name = shstrtab + sec->header.sh_name;
3432 }
3433
3434 for (i = 0; i < shnum; ++i) {
3435 struct obj_section *sec = f->sections[i];
3436
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003437 /* .modinfo should be contents only but gcc has no attribute for that.
3438 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3439 */
3440 if (strcmp(sec->name, ".modinfo") == 0)
3441 sec->header.sh_flags &= ~SHF_ALLOC;
3442
Eric Andersen9f16d612000-06-12 23:11:16 +00003443 if (sec->header.sh_flags & SHF_ALLOC)
3444 obj_insert_section_load_order(f, sec);
3445
3446 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 case SHT_SYMTAB:
3448 {
3449 unsigned long nsym, j;
3450 char *strtab;
3451 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003452
Eric Andersen3b1a7442003-12-24 20:30:45 +00003453 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3454 bb_error_msg("symbol size mismatch: %lu != %lu",
3455 (unsigned long) sec->header.sh_entsize,
3456 (unsigned long) sizeof(ElfW(Sym)));
3457 return NULL;
3458 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003459
Eric Andersen3b1a7442003-12-24 20:30:45 +00003460 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3461 strtab = f->sections[sec->header.sh_link]->contents;
3462 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003463
Eric Andersen3b1a7442003-12-24 20:30:45 +00003464 /* Allocate space for a table of local symbols. */
3465 j = f->local_symtab_size = sec->header.sh_info;
3466 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003467
Eric Andersen3b1a7442003-12-24 20:30:45 +00003468 /* Insert all symbols into the hash table. */
3469 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3470 ElfW(Addr) val = sym->st_value;
3471 const char *name;
3472 if (sym->st_name)
3473 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003474 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003475 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003476 else
3477 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003478
Eric Andersenbf833552003-08-13 19:56:33 +00003479#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003480 /*
3481 * For sh64 it is possible that the target of a branch
3482 * requires a mode switch (32 to 16 and back again).
3483 *
3484 * This is implied by the lsb being set in the target
3485 * address for SHmedia mode and clear for SHcompact.
3486 */
3487 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003488#endif
3489
Eric Andersen3b1a7442003-12-24 20:30:45 +00003490 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3491 val, sym->st_size);
3492 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003493 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003494 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003495
Eric Andersen3b1a7442003-12-24 20:30:45 +00003496 case SHT_RELM:
3497 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3498 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3499 (unsigned long) sec->header.sh_entsize,
3500 (unsigned long) sizeof(ElfW(RelM)));
3501 return NULL;
3502 }
3503 break;
3504 /* XXX Relocation code from modutils-2.3.19 is not here.
3505 * Why? That's about 20 lines of code from obj/obj_load.c,
3506 * which gets done in a second pass through the sections.
3507 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003508 }
3509 }
3510
3511 return f;
3512}
3513
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003514#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003515/*
3516 * load the unloaded sections directly into the memory allocated by
3517 * kernel for the module
3518 */
3519
Eric Andersenac5dbd12001-08-22 05:26:08 +00003520static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003521{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003522 ElfW(Addr) base = f->baseaddr;
3523 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003524
Eric Andersen8ae319a2001-05-21 16:09:18 +00003525 for (sec = f->load_order; sec; sec = sec->load_next) {
3526
3527 /* section already loaded? */
3528 if (sec->contents != NULL)
3529 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003530
Eric Andersen8ae319a2001-05-21 16:09:18 +00003531 if (sec->header.sh_size == 0)
3532 continue;
3533
3534 sec->contents = imagebase + (sec->header.sh_addr - base);
3535 fseek(fp, sec->header.sh_offset, SEEK_SET);
3536 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003537 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003538 return 0;
3539 }
3540
3541 }
3542 return 1;
3543}
3544#endif
3545
Eric Andersen9f16d612000-06-12 23:11:16 +00003546static void hide_special_symbols(struct obj_file *f)
3547{
3548 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003549 SPFX "cleanup_module",
3550 SPFX "init_module",
3551 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003552 NULL
3553 };
3554
3555 struct obj_symbol *sym;
3556 const char *const *p;
3557
3558 for (p = specials; *p; ++p)
3559 if ((sym = obj_find_symbol(f, *p)) != NULL)
3560 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003561 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003562}
3563
Glenn L McGrath759515c2003-08-30 06:00:33 +00003564
Eric Andersen71ae64b2002-10-10 04:20:21 +00003565#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003566static int obj_gpl_license(struct obj_file *f, const char **license)
3567{
3568 struct obj_section *sec;
3569 /* This list must match *exactly* the list of allowable licenses in
3570 * linux/include/linux/module.h. Checking for leading "GPL" will not
3571 * work, somebody will use "GPL sucks, this is proprietary".
3572 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003573 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003574 "GPL",
3575 "GPL v2",
3576 "GPL and additional rights",
3577 "Dual BSD/GPL",
3578 "Dual MPL/GPL",
3579 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003580
Eric Andersen166fa462002-09-16 05:30:24 +00003581 if ((sec = obj_find_section(f, ".modinfo"))) {
3582 const char *value, *ptr, *endptr;
3583 ptr = sec->contents;
3584 endptr = ptr + sec->header.sh_size;
3585 while (ptr < endptr) {
3586 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3587 int i;
3588 if (license)
3589 *license = value+1;
3590 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3591 if (strcmp(value+1, gpl_licenses[i]) == 0)
3592 return(0);
3593 }
3594 return(2);
3595 }
3596 if (strchr(ptr, '\0'))
3597 ptr = strchr(ptr, '\0') + 1;
3598 else
3599 ptr = endptr;
3600 }
3601 }
3602 return(1);
3603}
3604
3605#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3606#define TAINT_PROPRIETORY_MODULE (1<<0)
3607#define TAINT_FORCED_MODULE (1<<1)
3608#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003609#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003610
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003611static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003612 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3613{
3614 char buf[80];
3615 int oldval;
3616 static int first = 1;
3617 if (fd < 0 && !kernel_has_tainted)
3618 return; /* New modutils on old kernel */
3619 printf("Warning: loading %s will taint the kernel: %s%s\n",
3620 m_name, text1, text2);
3621 if (first) {
3622 printf(" See %s for information about tainted modules\n", TAINT_URL);
3623 first = 0;
3624 }
3625 if (fd >= 0) {
3626 read(fd, buf, sizeof(buf)-1);
3627 buf[sizeof(buf)-1] = '\0';
3628 oldval = strtoul(buf, NULL, 10);
3629 sprintf(buf, "%d\n", oldval | taint);
3630 write(fd, buf, strlen(buf));
3631 }
3632}
3633
3634/* Check if loading this module will taint the kernel. */
3635static void check_tainted_module(struct obj_file *f, char *m_name)
3636{
3637 static const char tainted_file[] = TAINT_FILENAME;
3638 int fd, kernel_has_tainted;
3639 const char *ptr;
3640
3641 kernel_has_tainted = 1;
3642 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3643 if (errno == ENOENT)
3644 kernel_has_tainted = 0;
3645 else if (errno == EACCES)
3646 kernel_has_tainted = 1;
3647 else {
3648 perror(tainted_file);
3649 kernel_has_tainted = 0;
3650 }
3651 }
3652
3653 switch (obj_gpl_license(f, &ptr)) {
3654 case 0:
3655 break;
3656 case 1:
3657 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3658 break;
3659 case 2:
3660 /* The module has a non-GPL license so we pretend that the
3661 * kernel always has a taint flag to get a warning even on
3662 * kernels without the proc flag.
3663 */
3664 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3665 break;
3666 default:
3667 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3668 break;
3669 }
3670
3671 if (flag_force_load)
3672 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3673
3674 if (fd >= 0)
3675 close(fd);
3676}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003677#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3678#define check_tainted_module(x, y) do { } while(0);
3679#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003680
Eric Andersen889dd202003-01-23 04:48:34 +00003681#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3682/* add module source, timestamp, kernel version and a symbol for the
3683 * start of some sections. this info is used by ksymoops to do better
3684 * debugging.
3685 */
3686static int
3687get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3688{
3689#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003690 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003691#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003692 strncpy(str, "???", sizeof(str));
3693 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003694#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3695}
3696
3697/* add module source, timestamp, kernel version and a symbol for the
3698 * start of some sections. this info is used by ksymoops to do better
3699 * debugging.
3700 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003701static void
Eric Andersen889dd202003-01-23 04:48:34 +00003702add_ksymoops_symbols(struct obj_file *f, const char *filename,
3703 const char *m_name)
3704{
3705 static const char symprefix[] = "__insmod_";
3706 struct obj_section *sec;
3707 struct obj_symbol *sym;
3708 char *name, *absolute_filename;
3709 char str[STRVERSIONLEN], real[PATH_MAX];
3710 int i, l, lm_name, lfilename, use_ksymtab, version;
3711 struct stat statbuf;
3712
3713 static const char *section_names[] = {
3714 ".text",
3715 ".rodata",
3716 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003717 ".bss",
3718 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003719 };
3720
3721 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003722 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003723 }
3724 else {
3725 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003726 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003727 errno = save_errno;
3728 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003729 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003730 }
3731
3732 lm_name = strlen(m_name);
3733 lfilename = strlen(absolute_filename);
3734
3735 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3736 * are not to be exported. otherwise leave ksymtab alone for now, the
3737 * "export all symbols" compatibility code will export these symbols later.
3738 */
3739 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3740
3741 if ((sec = obj_find_section(f, ".this"))) {
3742 /* tag the module header with the object name, last modified
3743 * timestamp and module version. worst case for module version
3744 * is 0xffffff, decimal 16777215. putting all three fields in
3745 * one symbol is less readable but saves kernel space.
3746 */
3747 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003748 lm_name+ /* module name */
3749 2+ /* "_O" */
3750 lfilename+ /* object filename */
3751 2+ /* "_M" */
3752 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3753 2+ /* "_V" */
3754 8+ /* version in dec */
3755 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003756 name = xmalloc(l);
3757 if (stat(absolute_filename, &statbuf) != 0)
3758 statbuf.st_mtime = 0;
3759 version = get_module_version(f, str); /* -1 if not found */
3760 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003761 symprefix, m_name, absolute_filename,
3762 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3763 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003764 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003765 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003766 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003767 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003768 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003769 }
3770 free(absolute_filename);
3771#ifdef _NOT_SUPPORTED_
3772 /* record where the persistent data is going, same address as previous symbol */
3773
3774 if (f->persist) {
3775 l = sizeof(symprefix)+ /* "__insmod_" */
3776 lm_name+ /* module name */
3777 2+ /* "_P" */
3778 strlen(f->persist)+ /* data store */
3779 1; /* nul */
3780 name = xmalloc(l);
3781 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003782 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003783 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003784 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003785 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003786 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003787 }
3788#endif /* _NOT_SUPPORTED_ */
3789 /* tag the desired sections if size is non-zero */
3790
3791 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3792 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003793 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003794 l = sizeof(symprefix)+ /* "__insmod_" */
3795 lm_name+ /* module name */
3796 2+ /* "_S" */
3797 strlen(sec->name)+ /* section name */
3798 2+ /* "_L" */
3799 8+ /* length in dec */
3800 1; /* nul */
3801 name = xmalloc(l);
3802 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003803 symprefix, m_name, sec->name,
3804 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003805 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003806 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003807 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003809 }
3810 }
3811}
3812#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3813
Eric Andersenbe65c352003-01-23 04:57:35 +00003814#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3815static void print_load_map(struct obj_file *f)
3816{
3817 struct obj_symbol *sym;
3818 struct obj_symbol **all, **p;
3819 struct obj_section *sec;
3820 int i, nsyms, *loaded;
3821
3822 /* Report on the section layout. */
3823
3824 printf("Sections: Size %-*s Align\n",
3825 (int) (2 * sizeof(void *)), "Address");
3826
3827 for (sec = f->load_order; sec; sec = sec->load_next) {
3828 int a;
3829 unsigned long tmp;
3830
3831 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3832 tmp >>= 1;
3833 if (a == -1)
3834 a = 0;
3835
3836 printf("%-15s %08lx %0*lx 2**%d\n",
3837 sec->name,
3838 (long)sec->header.sh_size,
3839 (int) (2 * sizeof(void *)),
3840 (long)sec->header.sh_addr,
3841 a);
3842 }
3843#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3844 /* Quick reference which section indicies are loaded. */
3845
3846 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3847 while (--i >= 0)
3848 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3849
3850 /* Collect the symbols we'll be listing. */
3851
3852 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3853 for (sym = f->symtab[i]; sym; sym = sym->next)
3854 if (sym->secidx <= SHN_HIRESERVE
3855 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3856 ++nsyms;
3857
3858 all = alloca(nsyms * sizeof(struct obj_symbol *));
3859
3860 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3861 for (sym = f->symtab[i]; sym; sym = sym->next)
3862 if (sym->secidx <= SHN_HIRESERVE
3863 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3864 *p++ = sym;
3865
3866 /* And list them. */
3867 printf("\nSymbols:\n");
3868 for (p = all; p < all + nsyms; ++p) {
3869 char type = '?';
3870 unsigned long value;
3871
3872 sym = *p;
3873 if (sym->secidx == SHN_ABS) {
3874 type = 'A';
3875 value = sym->value;
3876 } else if (sym->secidx == SHN_UNDEF) {
3877 type = 'U';
3878 value = 0;
3879 } else {
3880 sec = f->sections[sym->secidx];
3881
3882 if (sec->header.sh_type == SHT_NOBITS)
3883 type = 'B';
3884 else if (sec->header.sh_flags & SHF_ALLOC) {
3885 if (sec->header.sh_flags & SHF_EXECINSTR)
3886 type = 'T';
3887 else if (sec->header.sh_flags & SHF_WRITE)
3888 type = 'D';
3889 else
3890 type = 'R';
3891 }
3892 value = sym->value + sec->header.sh_addr;
3893 }
3894
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003895 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003896 type = tolower(type);
3897
3898 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3899 type, sym->name);
3900 }
3901#endif
3902}
3903
3904#endif
3905
Eric Andersen9f16d612000-06-12 23:11:16 +00003906extern int insmod_main( int argc, char **argv)
3907{
Eric Andersena18aaf12001-01-24 19:07:09 +00003908 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003909 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003910 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003911 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003912 unsigned long m_size;
3913 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003914 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003915 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003916 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003917 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003919#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003920 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003921 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003922 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003923#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003924#ifdef CONFIG_FEATURE_CLEAN_UP
3925 FILE *fp = 0;
3926#else
3927 FILE *fp;
3928#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003929#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3930 int flag_print_load_map = 0;
3931#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003932 int k_version = 0;
3933 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003934
Erik Andersene49d5ec2000-02-08 19:58:47 +00003935 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003936#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003937 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003938#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003939 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003940#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003941 {
3942 switch (opt) {
3943 case 'f': /* force loading */
3944 flag_force_load = 1;
3945 break;
3946 case 'k': /* module loaded by kerneld, auto-cleanable */
3947 flag_autoclean = 1;
3948 break;
3949 case 's': /* log to syslog */
3950 /* log to syslog -- not supported */
3951 /* but kernel needs this for request_module(), */
3952 /* as this calls: modprobe -k -s -- <module> */
3953 /* so silently ignore this flag */
3954 break;
3955 case 'v': /* verbose output */
3956 flag_verbose = 1;
3957 break;
3958 case 'q': /* silent */
3959 flag_quiet = 1;
3960 break;
3961 case 'x': /* do not export externs */
3962 flag_export = 0;
3963 break;
3964 case 'o': /* name the output module */
3965 free(m_name);
3966 m_name = bb_xstrdup(optarg);
3967 break;
3968 case 'L': /* Stub warning */
3969 /* This is needed for compatibility with modprobe.
3970 * In theory, this does locking, but we don't do
3971 * that. So be careful and plan your life around not
3972 * loading the same module 50 times concurrently. */
3973 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003974#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003975 case 'm': /* print module load map */
3976 flag_print_load_map = 1;
3977 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003978#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003979 default:
3980 bb_show_usage();
3981 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003982 }
Eric Andersen03d80912003-12-19 21:04:19 +00003983
Eric Andersena18aaf12001-01-24 19:07:09 +00003984 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003985 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003986 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003987
Erik Andersene49d5ec2000-02-08 19:58:47 +00003988 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003989 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003990 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003991 len = strlen(tmp);
3992
Eric Andersen03d80912003-12-19 21:04:19 +00003993 if (uname(&myuname) == 0) {
3994 if (myuname.release[0] == '2') {
3995 k_version = myuname.release[2] - '0';
3996 }
3997 }
3998
3999#if defined(CONFIG_FEATURE_2_6_MODULES)
4000 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004001 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004002 len-=3;
4003 tmp[len] = '\0';
4004 }
4005 else
4006#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004007 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4008 len-=2;
4009 tmp[len] = '\0';
4010 }
Eric Andersen2d342152002-06-18 05:16:25 +00004011
Eric Andersen03d80912003-12-19 21:04:19 +00004012
4013#if defined(CONFIG_FEATURE_2_6_MODULES)
4014 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004015 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004016 else
Eric Andersen03d80912003-12-19 21:04:19 +00004017#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004018 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004019
Eric Andersen61f83052002-06-22 17:15:42 +00004020 if (!m_name) {
4021 m_name = tmp;
4022 } else {
4023 free(tmp1);
4024 tmp1 = 0; /* flag for free(m_name) before exit() */
4025 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004026
Eric Andersen14d35432001-05-14 17:07:32 +00004027 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004028 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4029 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004030 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4031 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004032 if (k_version) { /* uname succeedd */
4033 char *module_dir;
4034 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004035 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004036
Eric Andersen03d80912003-12-19 21:04:19 +00004037 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004038 /* Jump through hoops in case /lib/modules/`uname -r`
4039 * is a symlink. We do not want recursive_action to
4040 * follow symlinks, but we do want to follow the
4041 * /lib/modules/`uname -r` dir, So resolve it ourselves
4042 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004043 if (realpath (tmdn, real_module_dir) == NULL)
4044 module_dir = tmdn;
4045 else
4046 module_dir = real_module_dir;
4047 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004048 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004049 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004050 }
4051
4052 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004053 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004054 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004055 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004056
Eric Andersen03d80912003-12-19 21:04:19 +00004057 free(m_filename);
4058 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004059 if (realpath (_PATH_MODULES, module_dir) == NULL)
4060 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004061 /* No module found under /lib/modules/`uname -r`, this
4062 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004063 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004064 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004065 {
Eric Andersen61f83052002-06-22 17:15:42 +00004066 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004067 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004068 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004069 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004070 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004071 }
4072 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004073 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004074 }
Eric Andersen03d80912003-12-19 21:04:19 +00004075 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004076 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004077
Rob Landley999af202005-12-11 20:14:12 +00004078 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004079 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004080
Eric Andersene7047882003-12-11 01:42:13 +00004081#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004082 if (k_version > 4)
4083 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004084 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004085 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004086 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004087 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004088#endif
4089
Eric Andersen8ae319a2001-05-21 16:09:18 +00004090 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004091 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004092
Eric Andersen9f16d612000-06-12 23:11:16 +00004093 if (get_modinfo_value(f, "kernel_version") == NULL)
4094 m_has_modinfo = 0;
4095 else
4096 m_has_modinfo = 1;
4097
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004098#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004099 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004100 if (!flag_quiet) {
4101 if (uname(&uts_info) < 0)
4102 uts_info.release[0] = '\0';
4103 if (m_has_modinfo) {
4104 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004105 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004106 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004107 "compiled for");
4108 goto out;
4109 }
4110 }
4111
4112 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4113 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004114 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004115 "\t%s was compiled for kernel version %s\n"
4116 "\twhile this kernel is version %s",
4117 m_filename, m_strversion, uts_info.release);
4118 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004119 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004120 "\t%s was compiled for kernel version %s\n"
4121 "\twhile this kernel is version %s.",
4122 m_filename, m_strversion, uts_info.release);
4123 goto out;
4124 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004125 }
4126 }
4127 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004128#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004129
Eric Andersencb3b9b12004-06-22 11:50:52 +00004130 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004131 if (!new_get_kernel_symbols())
4132 goto out;
4133 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004134 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004135 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004136 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 }
4138
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004139#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004140 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004141 if (m_has_modinfo)
4142 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004143
4144 if (m_crcs != k_crcs)
4145 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004146#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004147
Erik Andersene49d5ec2000-02-08 19:58:47 +00004148 /* Let the module know about the kernel symbols. */
4149 add_kernel_symbols(f);
4150
Eric Andersen9f16d612000-06-12 23:11:16 +00004151 /* Allocate common symbols, symbol tables, and string tables. */
4152
Eric Andersencb3b9b12004-06-22 11:50:52 +00004153 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004154 {
4155 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004156 }
4157
Eric Andersen9f16d612000-06-12 23:11:16 +00004158 if (!obj_check_undefineds(f)) {
4159 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004160 }
4161 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004162 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004163
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004164 /* done with the module name, on to the optional var=value arguments */
4165 ++optind;
4166
Eric Andersen9f16d612000-06-12 23:11:16 +00004167 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004168 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004169 {
4170 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004171 }
4172 }
4173
Eric Andersen9f16d612000-06-12 23:11:16 +00004174 arch_create_got(f);
4175 hide_special_symbols(f);
4176
Eric Andersen889dd202003-01-23 04:48:34 +00004177#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4178 add_ksymoops_symbols(f, m_filename, m_name);
4179#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4180
Eric Andersencb3b9b12004-06-22 11:50:52 +00004181 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004182
Erik Andersene49d5ec2000-02-08 19:58:47 +00004183 /* Find current size of the module */
4184 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004185
4186
Erik Andersene49d5ec2000-02-08 19:58:47 +00004187 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004188 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004189 case EEXIST:
4190 bb_error_msg("A module named %s already exists", m_name);
4191 goto out;
4192 case ENOMEM:
4193 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4194 m_size);
4195 goto out;
4196 default:
4197 bb_perror_msg("create_module: %s", m_name);
4198 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004199 }
Erik Andersend387d011999-12-21 02:55:11 +00004200
Eric Andersen8ae319a2001-05-21 16:09:18 +00004201#if !LOADBITS
4202 /*
4203 * the PROGBITS section was not loaded by the obj_load
4204 * now we can load them directly into the kernel memory
4205 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004206 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004207 delete_module(m_name);
4208 goto out;
4209 }
Eric Andersen03d80912003-12-19 21:04:19 +00004210#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004211
Eric Andersen9f16d612000-06-12 23:11:16 +00004212 if (!obj_relocate(f, m_addr)) {
4213 delete_module(m_name);
4214 goto out;
4215 }
Erik Andersend387d011999-12-21 02:55:11 +00004216
Eric Andersencb3b9b12004-06-22 11:50:52 +00004217 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004218 {
4219 delete_module(m_name);
4220 goto out;
4221 }
4222
Eric Andersenbe65c352003-01-23 04:57:35 +00004223#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4224 if(flag_print_load_map)
4225 print_load_map(f);
4226#endif
4227
Matt Kraai3e856ce2000-12-01 02:55:13 +00004228 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004229
4230out:
Eric Andersen61f83052002-06-22 17:15:42 +00004231#ifdef CONFIG_FEATURE_CLEAN_UP
4232 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004233 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004234 free(tmp1);
4235 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004236 free(m_name);
4237 }
4238 free(m_filename);
4239#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004240 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004241}
Eric Andersene7047882003-12-11 01:42:13 +00004242
4243
4244#endif
4245
4246
4247#ifdef CONFIG_FEATURE_2_6_MODULES
4248
4249#include <sys/mman.h>
4250#include <asm/unistd.h>
4251#include <sys/syscall.h>
4252
4253/* We use error numbers in a loose translation... */
4254static const char *moderror(int err)
4255{
4256 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004257 case ENOEXEC:
4258 return "Invalid module format";
4259 case ENOENT:
4260 return "Unknown symbol in module";
4261 case ESRCH:
4262 return "Module has wrong symbol version";
4263 case EINVAL:
4264 return "Invalid parameters";
4265 default:
4266 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004267 }
4268}
4269
4270extern int insmod_ng_main( int argc, char **argv)
4271{
4272 int i;
4273 int fd;
4274 long int ret;
4275 struct stat st;
4276 unsigned long len;
4277 void *map;
4278 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004279
Eric Andersene7047882003-12-11 01:42:13 +00004280 filename = argv[1];
4281 if (!filename) {
4282 bb_show_usage();
4283 return -1;
4284 }
4285
4286 /* Rest is options */
4287 for (i = 2; i < argc; i++) {
4288 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4289 /* Spaces handled by "" pairs, but no way of escaping quotes */
4290 if (strchr(argv[i], ' ')) {
4291 strcat(options, "\"");
4292 strcat(options, argv[i]);
4293 strcat(options, "\"");
4294 } else {
4295 strcat(options, argv[i]);
4296 }
4297 strcat(options, " ");
4298 }
4299
4300 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4301 bb_perror_msg_and_die("cannot open module `%s'", filename);
4302 }
4303
4304 fstat(fd, &st);
4305 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004306 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004307 if (map == MAP_FAILED) {
4308 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4309 }
4310
4311 ret = syscall(__NR_init_module, map, len, options);
4312 if (ret != 0) {
4313 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004315 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004316
Eric Andersene7047882003-12-11 01:42:13 +00004317 return 0;
4318}
4319
4320#endif