blob: 96d9d5b7d5a7b8d53c1d2d4549e2b3519abc66c7 [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: */
Eric Andersenbf833552003-08-13 19:56:33 +0000271#if defined(__sh__) && defined(__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
514#if __BYTE_ORDER == __LITTLE_ENDIAN
515#define ELFDATAM ELFDATA2LSB
516#elif __BYTE_ORDER == __BIG_ENDIAN
517#define ELFDATAM ELFDATA2MSB
518#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
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001300#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001301
Eric Andersen3b1a7442003-12-24 20:30:45 +00001302 case R_PPC_ADDR16_HA:
1303 *(unsigned short *)loc = (v + 0x8000) >> 16;
1304 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001305
Eric Andersen3b1a7442003-12-24 20:30:45 +00001306 case R_PPC_ADDR16_HI:
1307 *(unsigned short *)loc = v >> 16;
1308 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001309
Eric Andersen3b1a7442003-12-24 20:30:45 +00001310 case R_PPC_ADDR16_LO:
1311 *(unsigned short *)loc = v;
1312 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001313
Eric Andersen3b1a7442003-12-24 20:30:45 +00001314 case R_PPC_REL24:
1315 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001316
Eric Andersen3b1a7442003-12-24 20:30:45 +00001317 case R_PPC_REL32:
1318 *loc = v - dot;
1319 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001320
Eric Andersen3b1a7442003-12-24 20:30:45 +00001321 case R_PPC_ADDR32:
1322 *loc = v;
1323 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001324
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001325#elif defined(__s390__)
1326
1327 case R_390_32:
1328 *(unsigned int *) loc += v;
1329 break;
1330 case R_390_16:
1331 *(unsigned short *) loc += v;
1332 break;
1333 case R_390_8:
1334 *(unsigned char *) loc += v;
1335 break;
1336
1337 case R_390_PC32:
1338 *(unsigned int *) loc += v - dot;
1339 break;
1340 case R_390_PC16DBL:
1341 *(unsigned short *) loc += (v - dot) >> 1;
1342 break;
1343 case R_390_PC16:
1344 *(unsigned short *) loc += v - dot;
1345 break;
1346
1347 case R_390_PLT32:
1348 case R_390_PLT16DBL:
1349 /* find the plt entry and initialize it. */
1350 assert(isym != NULL);
1351 pe = (struct arch_single_entry *) &isym->pltent;
1352 assert(pe->allocated);
1353 if (pe->inited == 0) {
1354 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1355 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1356 ip[1] = 0x100607f1;
1357 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1358 ip[2] = v - 2;
1359 else
1360 ip[2] = v;
1361 pe->inited = 1;
1362 }
1363
1364 /* Insert relative distance to target. */
1365 v = plt + pe->offset - dot;
1366 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1367 *(unsigned int *) loc = (unsigned int) v;
1368 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1369 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1370 break;
1371
1372 case R_390_GLOB_DAT:
1373 case R_390_JMP_SLOT:
1374 *loc = v;
1375 break;
1376
1377 case R_390_RELATIVE:
1378 *loc += f->baseaddr;
1379 break;
1380
1381 case R_390_GOTPC:
1382 assert(got != 0);
1383 *(unsigned long *) loc += got - dot;
1384 break;
1385
1386 case R_390_GOT12:
1387 case R_390_GOT16:
1388 case R_390_GOT32:
1389 assert(isym != NULL);
1390 assert(got != 0);
1391 if (!isym->gotent.inited)
1392 {
1393 isym->gotent.inited = 1;
1394 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1395 }
1396 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1397 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1398 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1399 *(unsigned short *) loc += isym->gotent.offset;
1400 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1401 *(unsigned int *) loc += isym->gotent.offset;
1402 break;
1403
1404# ifndef R_390_GOTOFF32
1405# define R_390_GOTOFF32 R_390_GOTOFF
1406# endif
1407 case R_390_GOTOFF32:
1408 assert(got != 0);
1409 *loc += v - got;
1410 break;
1411
Eric Andersencffd5022002-05-24 06:50:15 +00001412#elif defined(__sh__)
1413
Eric Andersen3b1a7442003-12-24 20:30:45 +00001414 case R_SH_NONE:
1415 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001416
Eric Andersen3b1a7442003-12-24 20:30:45 +00001417 case R_SH_DIR32:
1418 *loc += v;
1419 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001420
Eric Andersen3b1a7442003-12-24 20:30:45 +00001421 case R_SH_REL32:
1422 *loc += v - dot;
1423 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001424
Eric Andersen3b1a7442003-12-24 20:30:45 +00001425 case R_SH_PLT32:
1426 *loc = v - dot;
1427 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001428
Eric Andersen3b1a7442003-12-24 20:30:45 +00001429 case R_SH_GLOB_DAT:
1430 case R_SH_JMP_SLOT:
1431 *loc = v;
1432 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001433
Eric Andersen3b1a7442003-12-24 20:30:45 +00001434 case R_SH_RELATIVE:
1435 *loc = f->baseaddr + rel->r_addend;
1436 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001437
Eric Andersen3b1a7442003-12-24 20:30:45 +00001438 case R_SH_GOTPC:
1439 assert(got != 0);
1440 *loc = got - dot + rel->r_addend;
1441 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001442
Eric Andersen3b1a7442003-12-24 20:30:45 +00001443 case R_SH_GOT32:
1444 goto bb_use_got;
1445
1446 case R_SH_GOTOFF:
1447 assert(got != 0);
1448 *loc = v - got;
1449 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001450
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001451# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001452 case R_SH_IMM_MEDLOW16:
1453 case R_SH_IMM_LOW16:
1454 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001455 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001456
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001457 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001458 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001459
Eric Andersen3b1a7442003-12-24 20:30:45 +00001460 /*
1461 * movi and shori have the format:
1462 *
1463 * | op | imm | reg | reserved |
1464 * 31..26 25..10 9.. 4 3 .. 0
1465 *
1466 * so we simply mask and or in imm.
1467 */
1468 word = *loc & ~0x3fffc00;
1469 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001470
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001472
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 break;
1474 }
Eric Andersenbf833552003-08-13 19:56:33 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 case R_SH_IMM_MEDLOW16_PCREL:
1477 case R_SH_IMM_LOW16_PCREL:
1478 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001479 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001480
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001482
Eric Andersen3b1a7442003-12-24 20:30:45 +00001483 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001484
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001485 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001487
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001491
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492 break;
1493 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001494# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001495
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001496#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001497
Eric Andersen3b1a7442003-12-24 20:30:45 +00001498 case R_V850_NONE:
1499 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001500
Eric Andersen3b1a7442003-12-24 20:30:45 +00001501 case R_V850_32:
1502 /* We write two shorts instead of a long because even
1503 32-bit insns only need half-word alignment, but
1504 32-bit data needs to be long-word aligned. */
1505 v += ((unsigned short *)loc)[0];
1506 v += ((unsigned short *)loc)[1] << 16;
1507 ((unsigned short *)loc)[0] = v & 0xffff;
1508 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1509 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001510
Eric Andersen3b1a7442003-12-24 20:30:45 +00001511 case R_V850_22_PCREL:
1512 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001513
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001514#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001515
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001516 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001517 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001518
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001519 case R_X86_64_64:
1520 *loc += v;
1521 break;
1522
1523 case R_X86_64_32:
1524 *(unsigned int *) loc += v;
1525 if (v > 0xffffffff)
1526 {
1527 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1528 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1529 }
1530 break;
1531
1532 case R_X86_64_32S:
1533 *(signed int *) loc += v;
1534 break;
1535
1536 case R_X86_64_16:
1537 *(unsigned short *) loc += v;
1538 break;
1539
1540 case R_X86_64_8:
1541 *(unsigned char *) loc += v;
1542 break;
1543
1544 case R_X86_64_PC32:
1545 *(unsigned int *) loc += v - dot;
1546 break;
1547
1548 case R_X86_64_PC16:
1549 *(unsigned short *) loc += v - dot;
1550 break;
1551
1552 case R_X86_64_PC8:
1553 *(unsigned char *) loc += v - dot;
1554 break;
1555
1556 case R_X86_64_GLOB_DAT:
1557 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001558 *loc = v;
1559 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001560
1561 case R_X86_64_RELATIVE:
1562 *loc += f->baseaddr;
1563 break;
1564
1565 case R_X86_64_GOT32:
1566 case R_X86_64_GOTPCREL:
1567 goto bb_use_got;
1568# if 0
1569 assert(isym != NULL);
1570 if (!isym->gotent.reloc_done)
1571 {
1572 isym->gotent.reloc_done = 1;
1573 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1574 }
1575 /* XXX are these really correct? */
1576 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1577 *(unsigned int *) loc += v + isym->gotent.offset;
1578 else
1579 *loc += isym->gotent.offset;
1580 break;
1581# endif
1582
Mike Frysingerf982d862006-01-04 00:11:26 +00001583#else
1584# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001585#endif
1586
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001587 default:
1588 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1589 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001590 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001591
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001592#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001593
Eric Andersen3b1a7442003-12-24 20:30:45 +00001594bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001595
Eric Andersen3b1a7442003-12-24 20:30:45 +00001596 /* find the plt entry and initialize it if necessary */
1597 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001598
Eric Andersencffd5022002-05-24 06:50:15 +00001599#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001600 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1601 pe = pe->next;
1602 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001603#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001604 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001605#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001606
Eric Andersen3b1a7442003-12-24 20:30:45 +00001607 if (! pe->inited) {
1608 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001609
Eric Andersen3b1a7442003-12-24 20:30:45 +00001610 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001611
1612#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001613 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1614 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001615#endif
1616#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001617 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001618 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001619 ip[2] = 0x7d6903a6; /* mtctr r11 */
1620 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001621#endif
Miles Baderae28b042002-04-01 09:34:25 +00001622#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001623 /* We have to trash a register, so we assume that any control
1624 transfer more than 21-bits away must be a function call
1625 (so we can use a call-clobbered register). */
1626 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1627 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001628#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001629 pe->inited = 1;
1630 }
Eric Andersen21adca72000-12-06 18:18:26 +00001631
Eric Andersen3b1a7442003-12-24 20:30:45 +00001632 /* relative distance to target */
1633 v -= dot;
1634 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001635#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001636 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001637#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001638 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001639#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 /* go via the plt */
1641 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001642
1643#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001645#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001647#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001649
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001651#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 /* Convert to words. */
1653 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001654
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001656#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001659#endif
Miles Baderae28b042002-04-01 09:34:25 +00001660#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 /* We write two shorts instead of a long because even 32-bit insns
1662 only need half-word alignment, but the 32-bit data write needs
1663 to be long-word aligned. */
1664 ((unsigned short *)loc)[0] =
1665 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1666 | ((v >> 16) & 0x3f); /* offs high part */
1667 ((unsigned short *)loc)[1] =
1668 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001669#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001670 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001671#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001672
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001673#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001675
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 assert(isym != NULL);
1677 /* needs an entry in the .got: set it, once */
1678 if (!isym->gotent.inited) {
1679 isym->gotent.inited = 1;
1680 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1681 }
1682 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001683#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001685#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001687#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001689
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001690#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001691 }
1692
1693 return ret;
1694}
1695
Eric Andersencffd5022002-05-24 06:50:15 +00001696
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001697#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001698
1699static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1700 int offset, int size)
1701{
1702 struct arch_list_entry *pe;
1703
1704 for (pe = *list; pe != NULL; pe = pe->next) {
1705 if (pe->addend == rel->r_addend) {
1706 break;
1707 }
1708 }
1709
1710 if (pe == NULL) {
1711 pe = xmalloc(sizeof(struct arch_list_entry));
1712 pe->next = *list;
1713 pe->addend = rel->r_addend;
1714 pe->offset = offset;
1715 pe->inited = 0;
1716 *list = pe;
1717 return size;
1718 }
1719 return 0;
1720}
1721
1722#endif
1723
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001724#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001725
1726static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1727 int offset, int size)
1728{
1729 if (single->allocated == 0) {
1730 single->allocated = 1;
1731 single->offset = offset;
1732 single->inited = 0;
1733 return size;
1734 }
1735 return 0;
1736}
1737
1738#endif
1739
1740#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1741
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001742static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001743 int offset, int size)
1744{
1745 struct obj_section *myrelsec = obj_find_section(f, name);
1746
1747 if (offset == 0) {
1748 offset += size;
1749 }
1750
1751 if (myrelsec) {
1752 obj_extend_section(myrelsec, offset);
1753 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001754 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001755 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001756 assert(myrelsec);
1757 }
1758
1759 return myrelsec;
1760}
1761
1762#endif
1763
1764static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001765{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001766#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001767 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001768 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001769#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001770 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001771#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001772#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001773 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001774#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001775 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001776 ElfW(RelM) *rel, *relend;
1777 ElfW(Sym) *symtab, *extsym;
1778 const char *strtab, *name;
1779 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001780
Eric Andersen21adca72000-12-06 18:18:26 +00001781 for (i = 0; i < f->header.e_shnum; ++i) {
1782 relsec = f->sections[i];
1783 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001784 continue;
1785
Eric Andersen21adca72000-12-06 18:18:26 +00001786 symsec = f->sections[relsec->header.sh_link];
1787 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001788
Eric Andersen21adca72000-12-06 18:18:26 +00001789 rel = (ElfW(RelM) *) relsec->contents;
1790 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1791 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001792 strtab = (const char *) strsec->contents;
1793
1794 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001795 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001796
Eric Andersencffd5022002-05-24 06:50:15 +00001797#if defined(CONFIG_USE_GOT_ENTRIES)
1798 got_allocate = 0;
1799#endif
1800#if defined(CONFIG_USE_PLT_ENTRIES)
1801 plt_allocate = 0;
1802#endif
1803
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001804 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001805#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001806 case R_ARM_PC24:
1807 case R_ARM_PLT32:
1808 plt_allocate = 1;
1809 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001810
Eric Andersen3b1a7442003-12-24 20:30:45 +00001811 case R_ARM_GOTOFF:
1812 case R_ARM_GOTPC:
1813 got_needed = 1;
1814 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001815
Eric Andersen3b1a7442003-12-24 20:30:45 +00001816 case R_ARM_GOT32:
1817 got_allocate = 1;
1818 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001819
Eric Andersen21adca72000-12-06 18:18:26 +00001820#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001821 case R_386_GOTPC:
1822 case R_386_GOTOFF:
1823 got_needed = 1;
1824 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001825
Eric Andersen3b1a7442003-12-24 20:30:45 +00001826 case R_386_GOT32:
1827 got_allocate = 1;
1828 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001829
1830#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001831 case R_PPC_REL24:
1832 plt_allocate = 1;
1833 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001834
1835#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001836 case R_68K_GOT32:
1837 got_allocate = 1;
1838 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001839
Eric Andersen16451a02004-03-19 12:16:18 +00001840#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001841 case R_68K_GOTOFF:
1842 got_needed = 1;
1843 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001844#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001845
1846#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001847 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001848 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001849 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001850
Eric Andersen3b1a7442003-12-24 20:30:45 +00001851 case R_SH_GOTPC:
1852 case R_SH_GOTOFF:
1853 got_needed = 1;
1854 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001855
1856#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001857 case R_V850_22_PCREL:
1858 plt_needed = 1;
1859 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001860
1861#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001862 default:
1863 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001864 }
1865
Eric Andersen21adca72000-12-06 18:18:26 +00001866 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001867 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001868 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001869 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001870 }
1871 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001872#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001873 if (got_allocate) {
1874 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001875 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001876 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001877
1878 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001879 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001880#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001881#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001882 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001883#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001884 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001885 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001886 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001887#else
1888 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001889 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001890 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001891#endif
1892 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001893 }
1894#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001895 }
Miles Baderae28b042002-04-01 09:34:25 +00001896 }
Eric Andersen21adca72000-12-06 18:18:26 +00001897
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001898#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001899 if (got_needed) {
1900 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001901 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001902 }
Eric Andersen21adca72000-12-06 18:18:26 +00001903#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001904
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001905#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001906 if (plt_needed) {
1907 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001908 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001909 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001910#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001911
1912#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001913}
1914
Eric Andersen9f16d612000-06-12 23:11:16 +00001915/*======================================================================*/
1916
1917/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001918static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001919{
1920 unsigned long h = 0;
1921 unsigned long g;
1922 unsigned char ch;
1923
1924 while (n > 0) {
1925 ch = *name++;
1926 h = (h << 4) + ch;
1927 if ((g = (h & 0xf0000000)) != 0) {
1928 h ^= g >> 24;
1929 h &= ~g;
1930 }
1931 n--;
1932 }
1933 return h;
1934}
1935
Eric Andersen044228d2001-07-17 01:12:36 +00001936static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001937{
1938 return obj_elf_hash_n(name, strlen(name));
1939}
1940
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001941#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001942/* String comparison for non-co-versioned kernel and module. */
1943
1944static int ncv_strcmp(const char *a, const char *b)
1945{
1946 size_t alen = strlen(a), blen = strlen(b);
1947
1948 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1949 return strncmp(a, b, alen);
1950 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1951 return strncmp(a, b, blen);
1952 else
1953 return strcmp(a, b);
1954}
1955
1956/* String hashing for non-co-versioned kernel and module. Here
1957 we are simply forced to drop the crc from the hash. */
1958
1959static unsigned long ncv_symbol_hash(const char *str)
1960{
1961 size_t len = strlen(str);
1962 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1963 len -= 10;
1964 return obj_elf_hash_n(str, len);
1965}
1966
Eric Andersen044228d2001-07-17 01:12:36 +00001967static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001968obj_set_symbol_compare(struct obj_file *f,
1969 int (*cmp) (const char *, const char *),
1970 unsigned long (*hash) (const char *))
1971{
1972 if (cmp)
1973 f->symbol_cmp = cmp;
1974 if (hash) {
1975 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1976 int i;
1977
1978 f->symbol_hash = hash;
1979
1980 memcpy(tmptab, f->symtab, sizeof(tmptab));
1981 memset(f->symtab, 0, sizeof(f->symtab));
1982
1983 for (i = 0; i < HASH_BUCKETS; ++i)
1984 for (sym = tmptab[i]; sym; sym = next) {
1985 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1986 next = sym->next;
1987 sym->next = f->symtab[h];
1988 f->symtab[h] = sym;
1989 }
1990 }
1991}
1992
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001993#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001994
Eric Andersen044228d2001-07-17 01:12:36 +00001995static struct obj_symbol *
1996obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001997 unsigned long symidx, int info,
1998 int secidx, ElfW(Addr) value,
1999 unsigned long size)
2000{
2001 struct obj_symbol *sym;
2002 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002003 int n_type = ELF_ST_TYPE(info);
2004 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002005
2006 for (sym = f->symtab[hash]; sym; sym = sym->next)
2007 if (f->symbol_cmp(sym->name, name) == 0) {
2008 int o_secidx = sym->secidx;
2009 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002010 int o_type = ELF_ST_TYPE(o_info);
2011 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002012
2013 /* A redefinition! Is it legal? */
2014
2015 if (secidx == SHN_UNDEF)
2016 return sym;
2017 else if (o_secidx == SHN_UNDEF)
2018 goto found;
2019 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2020 /* Cope with local and global symbols of the same name
2021 in the same object file, as might have been created
2022 by ld -r. The only reason locals are now seen at this
2023 level at all is so that we can do semi-sensible things
2024 with parameters. */
2025
2026 struct obj_symbol *nsym, **p;
2027
2028 nsym = arch_new_symbol();
2029 nsym->next = sym->next;
2030 nsym->ksymidx = -1;
2031
2032 /* Excise the old (local) symbol from the hash chain. */
2033 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2034 continue;
2035 *p = sym = nsym;
2036 goto found;
2037 } else if (n_binding == STB_LOCAL) {
2038 /* Another symbol of the same name has already been defined.
2039 Just add this to the local table. */
2040 sym = arch_new_symbol();
2041 sym->next = NULL;
2042 sym->ksymidx = -1;
2043 f->local_symtab[symidx] = sym;
2044 goto found;
2045 } else if (n_binding == STB_WEAK)
2046 return sym;
2047 else if (o_binding == STB_WEAK)
2048 goto found;
2049 /* Don't unify COMMON symbols with object types the programmer
2050 doesn't expect. */
2051 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002052 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002053 return sym;
2054 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002055 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002056 goto found;
2057 else {
2058 /* Don't report an error if the symbol is coming from
2059 the kernel or some external module. */
2060 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002061 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002062 return sym;
2063 }
2064 }
2065
2066 /* Completely new symbol. */
2067 sym = arch_new_symbol();
2068 sym->next = f->symtab[hash];
2069 f->symtab[hash] = sym;
2070 sym->ksymidx = -1;
2071
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002072 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002073 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002074 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002075 name, (long) symidx, (long) f->local_symtab_size);
2076 else
2077 f->local_symtab[symidx] = sym;
2078 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002079
Eric Andersen3b1a7442003-12-24 20:30:45 +00002080found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002081 sym->name = name;
2082 sym->value = value;
2083 sym->size = size;
2084 sym->secidx = secidx;
2085 sym->info = info;
2086
2087 return sym;
2088}
2089
Eric Andersen044228d2001-07-17 01:12:36 +00002090static struct obj_symbol *
2091obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002092{
2093 struct obj_symbol *sym;
2094 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2095
2096 for (sym = f->symtab[hash]; sym; sym = sym->next)
2097 if (f->symbol_cmp(sym->name, name) == 0)
2098 return sym;
2099
2100 return NULL;
2101}
2102
Eric Andersen044228d2001-07-17 01:12:36 +00002103static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002104 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2105{
2106 if (sym) {
2107 if (sym->secidx >= SHN_LORESERVE)
2108 return sym->value;
2109
2110 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2111 } else {
2112 /* As a special case, a NULL sym has value zero. */
2113 return 0;
2114 }
2115}
2116
Eric Andersen044228d2001-07-17 01:12:36 +00002117static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002118{
2119 int i, n = f->header.e_shnum;
2120
2121 for (i = 0; i < n; ++i)
2122 if (strcmp(f->sections[i]->name, name) == 0)
2123 return f->sections[i];
2124
2125 return NULL;
2126}
2127
2128static int obj_load_order_prio(struct obj_section *a)
2129{
2130 unsigned long af, ac;
2131
2132 af = a->header.sh_flags;
2133
2134 ac = 0;
2135 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002136 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002137 ac |= 32;
2138 if (af & SHF_ALLOC)
2139 ac |= 16;
2140 if (!(af & SHF_WRITE))
2141 ac |= 8;
2142 if (af & SHF_EXECINSTR)
2143 ac |= 4;
2144 if (a->header.sh_type != SHT_NOBITS)
2145 ac |= 2;
2146
2147 return ac;
2148}
2149
Eric Andersen044228d2001-07-17 01:12:36 +00002150static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002151obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2152{
2153 struct obj_section **p;
2154 int prio = obj_load_order_prio(sec);
2155 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2156 if (obj_load_order_prio(*p) < prio)
2157 break;
2158 sec->load_next = *p;
2159 *p = sec;
2160}
2161
Eric Andersen044228d2001-07-17 01:12:36 +00002162static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002163 const char *name,
2164 unsigned long align,
2165 unsigned long size)
2166{
2167 int newidx = f->header.e_shnum++;
2168 struct obj_section *sec;
2169
2170 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2171 f->sections[newidx] = sec = arch_new_section();
2172
2173 memset(sec, 0, sizeof(*sec));
2174 sec->header.sh_type = SHT_PROGBITS;
2175 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2176 sec->header.sh_size = size;
2177 sec->header.sh_addralign = align;
2178 sec->name = name;
2179 sec->idx = newidx;
2180 if (size)
2181 sec->contents = xmalloc(size);
2182
2183 obj_insert_section_load_order(f, sec);
2184
2185 return sec;
2186}
2187
Eric Andersen044228d2001-07-17 01:12:36 +00002188static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002189 const char *name,
2190 unsigned long align,
2191 unsigned long size)
2192{
2193 int newidx = f->header.e_shnum++;
2194 struct obj_section *sec;
2195
2196 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2197 f->sections[newidx] = sec = arch_new_section();
2198
2199 memset(sec, 0, sizeof(*sec));
2200 sec->header.sh_type = SHT_PROGBITS;
2201 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2202 sec->header.sh_size = size;
2203 sec->header.sh_addralign = align;
2204 sec->name = name;
2205 sec->idx = newidx;
2206 if (size)
2207 sec->contents = xmalloc(size);
2208
2209 sec->load_next = f->load_order;
2210 f->load_order = sec;
2211 if (f->load_order_search_start == &f->load_order)
2212 f->load_order_search_start = &sec->load_next;
2213
2214 return sec;
2215}
2216
Eric Andersen044228d2001-07-17 01:12:36 +00002217static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002218{
2219 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002220 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002221 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2222 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002223 return sec->contents + oldsize;
2224}
2225
2226
Eric Andersen9f16d612000-06-12 23:11:16 +00002227/* Conditionally add the symbols from the given symbol set to the
2228 new module. */
2229
2230static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002231add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002232 int idx, struct new_module_symbol *syms, size_t nsyms)
2233{
2234 struct new_module_symbol *s;
2235 size_t i;
2236 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002237#ifdef SYMBOL_PREFIX
2238 char *name_buf = 0;
2239 size_t name_alloced_size = 0;
2240#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002241#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2242 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002243
Glenn L McGrath759515c2003-08-30 06:00:33 +00002244 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002245#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002246 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002247 /* Only add symbols that are already marked external.
2248 If we override locals we may cause problems for
2249 argument initialization. We will also create a false
2250 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002251 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002252 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002253
Glenn L McGrath759515c2003-08-30 06:00:33 +00002254 /* GPL licensed modules can use symbols exported with
2255 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2256 * exported names. Non-GPL modules never see any GPLONLY_
2257 * symbols so they cannot fudge it by adding the prefix on
2258 * their references.
2259 */
2260 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002261#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002262 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002263 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002264 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002265#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002266 continue;
2267 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002268 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002269
Miles Baderae28b042002-04-01 09:34:25 +00002270#ifdef SYMBOL_PREFIX
2271 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2272 kernel exports `C names', but module object files
2273 reference `linker names'). */
2274 size_t extra = sizeof SYMBOL_PREFIX;
2275 size_t name_size = strlen (name) + extra;
2276 if (name_size > name_alloced_size) {
2277 name_alloced_size = name_size * 2;
2278 name_buf = alloca (name_alloced_size);
2279 }
2280 strcpy (name_buf, SYMBOL_PREFIX);
2281 strcpy (name_buf + extra - 1, name);
2282 name = name_buf;
2283#endif /* SYMBOL_PREFIX */
2284
2285 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002286 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002287#ifdef SYMBOL_PREFIX
2288 /* Put NAME_BUF into more permanent storage. */
2289 name = xmalloc (name_size);
2290 strcpy (name, name_buf);
2291#endif
2292 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002293 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002294 STT_NOTYPE),
2295 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002296 /* Did our symbol just get installed? If so, mark the
2297 module as "used". */
2298 if (sym->secidx == idx)
2299 used = 1;
2300 }
2301 }
2302
2303 return used;
2304}
2305
2306static void add_kernel_symbols(struct obj_file *f)
2307{
2308 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002309 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002310
2311 /* Add module symbols first. */
2312
2313 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2314 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002315 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2316 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002317
2318 n_ext_modules_used = nused;
2319
2320 /* And finally the symbols from the kernel proper. */
2321
2322 if (nksyms)
2323 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2324}
2325
2326static char *get_modinfo_value(struct obj_file *f, const char *key)
2327{
2328 struct obj_section *sec;
2329 char *p, *v, *n, *ep;
2330 size_t klen = strlen(key);
2331
2332 sec = obj_find_section(f, ".modinfo");
2333 if (sec == NULL)
2334 return NULL;
2335 p = sec->contents;
2336 ep = p + sec->header.sh_size;
2337 while (p < ep) {
2338 v = strchr(p, '=');
2339 n = strchr(p, '\0');
2340 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002341 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002342 return v + 1;
2343 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002344 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002345 return n;
2346 }
2347 p = n + 1;
2348 }
2349
2350 return NULL;
2351}
2352
2353
2354/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002355/* Functions relating to module loading after 2.1.18. */
2356
2357static int
2358new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2359{
2360 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002361 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002362 struct obj_symbol *sym;
2363 char *contents, *loc;
2364 int min, max, n;
2365
2366 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002367 if ((q = strchr(p, '=')) == NULL) {
2368 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002369 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002370 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002371
2372 key = alloca(q - p + 6);
2373 memcpy(key, "parm_", 5);
2374 memcpy(key + 5, p, q - p);
2375 key[q - p + 5] = 0;
2376
2377 p = get_modinfo_value(f, key);
2378 key += 5;
2379 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002380 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002381 return 0;
2382 }
2383
Miles Baderae28b042002-04-01 09:34:25 +00002384#ifdef SYMBOL_PREFIX
2385 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2386 strcpy (sym_name, SYMBOL_PREFIX);
2387 strcat (sym_name, key);
2388#else
2389 sym_name = key;
2390#endif
2391 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002392
2393 /* Also check that the parameter was not resolved from the kernel. */
2394 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002395 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002396 return 0;
2397 }
2398
2399 if (isdigit(*p)) {
2400 min = strtoul(p, &p, 10);
2401 if (*p == '-')
2402 max = strtoul(p + 1, &p, 10);
2403 else
2404 max = min;
2405 } else
2406 min = max = 1;
2407
2408 contents = f->sections[sym->secidx]->contents;
2409 loc = contents + sym->value;
2410 n = (*++q != '\0');
2411
2412 while (1) {
2413 if ((*p == 's') || (*p == 'c')) {
2414 char *str;
2415
2416 /* Do C quoting if we begin with a ", else slurp the lot. */
2417 if (*q == '"') {
2418 char *r;
2419
2420 str = alloca(strlen(q));
2421 for (r = str, q++; *q != '"'; ++q, ++r) {
2422 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002423 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002424 key);
2425 return 0;
2426 } else if (*q == '\\')
2427 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002428 case 'a':
2429 *r = '\a';
2430 break;
2431 case 'b':
2432 *r = '\b';
2433 break;
2434 case 'e':
2435 *r = '\033';
2436 break;
2437 case 'f':
2438 *r = '\f';
2439 break;
2440 case 'n':
2441 *r = '\n';
2442 break;
2443 case 'r':
2444 *r = '\r';
2445 break;
2446 case 't':
2447 *r = '\t';
2448 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002449
Eric Andersen3b1a7442003-12-24 20:30:45 +00002450 case '0':
2451 case '1':
2452 case '2':
2453 case '3':
2454 case '4':
2455 case '5':
2456 case '6':
2457 case '7':
2458 {
2459 int c = *q - '0';
2460 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002461 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002462 if (q[1] >= '0' && q[1] <= '7')
2463 c = (c * 8) + *++q - '0';
2464 }
2465 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002466 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002467 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002468
Eric Andersen3b1a7442003-12-24 20:30:45 +00002469 default:
2470 *r = *q;
2471 break;
2472 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002473 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002474 }
2475 *r = '\0';
2476 ++q;
2477 } else {
2478 char *r;
2479
2480 /* In this case, the string is not quoted. We will break
2481 it using the coma (like for ints). If the user wants to
2482 include comas in a string, he just has to quote it */
2483
2484 /* Search the next coma */
2485 r = strchr(q, ',');
2486
2487 /* Found ? */
2488 if (r != (char *) NULL) {
2489 /* Recopy the current field */
2490 str = alloca(r - q + 1);
2491 memcpy(str, q, r - q);
2492
Eric Andersenaff114c2004-04-14 17:51:38 +00002493 /* I don't know if it is useful, as the previous case
2494 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002495 str[r - q] = '\0';
2496
2497 /* Keep next fields */
2498 q = r;
2499 } else {
2500 /* last string */
2501 str = q;
2502 q = "";
2503 }
2504 }
2505
2506 if (*p == 's') {
2507 /* Normal string */
2508 obj_string_patch(f, sym->secidx, loc - contents, str);
2509 loc += tgt_sizeof_char_p;
2510 } else {
2511 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002512 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002513
2514 /* Get the size of each member */
2515 /* Probably we should do that outside the loop ? */
2516 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002517 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002518 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002519 return 0;
2520 }
2521 charssize = strtoul(p + 1, (char **) NULL, 10);
2522
2523 /* Check length */
2524 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002525 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002526 charssize - 1);
2527 return 0;
2528 }
2529
2530 /* Copy to location */
2531 strcpy((char *) loc, str);
2532 loc += charssize;
2533 }
2534 } else {
2535 long v = strtoul(q, &q, 0);
2536 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002537 case 'b':
2538 *loc++ = v;
2539 break;
2540 case 'h':
2541 *(short *) loc = v;
2542 loc += tgt_sizeof_short;
2543 break;
2544 case 'i':
2545 *(int *) loc = v;
2546 loc += tgt_sizeof_int;
2547 break;
2548 case 'l':
2549 *(long *) loc = v;
2550 loc += tgt_sizeof_long;
2551 break;
2552
2553 default:
2554 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2555 return 0;
2556 }
2557 }
2558
2559retry_end_of_value:
2560 switch (*q) {
2561 case '\0':
2562 goto end_of_arg;
2563
2564 case ' ':
2565 case '\t':
2566 case '\n':
2567 case '\r':
2568 ++q;
2569 goto retry_end_of_value;
2570
2571 case ',':
2572 if (++n > max) {
2573 bb_error_msg("too many values for %s (max %d)", key, max);
2574 return 0;
2575 }
2576 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002577 break;
2578
2579 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002580 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002581 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002582 }
2583 }
2584
Eric Andersen3b1a7442003-12-24 20:30:45 +00002585end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002586 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002587 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002588 return 0;
2589 }
2590
2591 argc--, argv++;
2592 }
2593
2594 return 1;
2595}
2596
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002597#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002598static int new_is_module_checksummed(struct obj_file *f)
2599{
2600 const char *p = get_modinfo_value(f, "using_checksums");
2601 if (p)
2602 return atoi(p);
2603 else
2604 return 0;
2605}
2606
2607/* Get the module's kernel version in the canonical integer form. */
2608
2609static int
2610new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2611{
2612 char *p, *q;
2613 int a, b, c;
2614
2615 p = get_modinfo_value(f, "kernel_version");
2616 if (p == NULL)
2617 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002618 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002619
2620 a = strtoul(p, &p, 10);
2621 if (*p != '.')
2622 return -1;
2623 b = strtoul(p + 1, &p, 10);
2624 if (*p != '.')
2625 return -1;
2626 c = strtoul(p + 1, &q, 10);
2627 if (p + 1 == q)
2628 return -1;
2629
2630 return a << 16 | b << 8 | c;
2631}
2632
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002633#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002634
2635
Eric Andersen9f16d612000-06-12 23:11:16 +00002636/* Fetch the loaded modules, and all currently exported symbols. */
2637
2638static int new_get_kernel_symbols(void)
2639{
2640 char *module_names, *mn;
2641 struct external_module *modules, *m;
2642 struct new_module_symbol *syms, *s;
2643 size_t ret, bufsize, nmod, nsyms, i, j;
2644
2645 /* Collect the loaded modules. */
2646
2647 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002648retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002649 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002650 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002651 module_names = xrealloc(module_names, bufsize = ret);
2652 goto retry_modules_load;
2653 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002654 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002655 return 0;
2656 }
2657
2658 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002659
2660 /* Collect the modules' symbols. */
2661
Mark Whitley94fd4802001-03-12 23:08:34 +00002662 if (nmod){
2663 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2664 memset(modules, 0, nmod * sizeof(*modules));
2665 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002666 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002667 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002668
Mark Whitley94fd4802001-03-12 23:08:34 +00002669 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2670 if (errno == ENOENT) {
2671 /* The module was removed out from underneath us. */
2672 continue;
2673 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002674 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002675 return 0;
2676 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002677
Mark Whitley94fd4802001-03-12 23:08:34 +00002678 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002679retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002680 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2681 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002682 case ENOSPC:
2683 syms = xrealloc(syms, bufsize = ret);
2684 goto retry_mod_sym_load;
2685 case ENOENT:
2686 /* The module was removed out from underneath us. */
2687 continue;
2688 default:
2689 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2690 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002691 }
2692 }
2693 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002694
Mark Whitley94fd4802001-03-12 23:08:34 +00002695 m->name = mn;
2696 m->addr = info.addr;
2697 m->nsyms = nsyms;
2698 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002699
Mark Whitley94fd4802001-03-12 23:08:34 +00002700 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2701 s->name += (unsigned long) syms;
2702 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002703 }
2704 }
2705
2706 /* Collect the kernel's symbols. */
2707
2708 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002709retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002710 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002711 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002712 syms = xrealloc(syms, bufsize = ret);
2713 goto retry_kern_sym_load;
2714 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002715 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 return 0;
2717 }
2718 nksyms = nsyms = ret;
2719 ksyms = syms;
2720
2721 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2722 s->name += (unsigned long) syms;
2723 }
2724 return 1;
2725}
2726
2727
2728/* Return the kernel symbol checksum version, or zero if not used. */
2729
2730static int new_is_kernel_checksummed(void)
2731{
2732 struct new_module_symbol *s;
2733 size_t i;
2734
2735 /* Using_Versions is not the first symbol, but it should be in there. */
2736
2737 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2738 if (strcmp((char *) s->name, "Using_Versions") == 0)
2739 return s->value;
2740
2741 return 0;
2742}
2743
2744
2745static int new_create_this_module(struct obj_file *f, const char *m_name)
2746{
2747 struct obj_section *sec;
2748
2749 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002750 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002751 memset(sec->contents, 0, sizeof(struct new_module));
2752
Miles Baderae28b042002-04-01 09:34:25 +00002753 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002754 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002755 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002756
2757 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002758 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002759
2760 return 1;
2761}
2762
Eric Andersen889dd202003-01-23 04:48:34 +00002763#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2764/* add an entry to the __ksymtab section, creating it if necessary */
2765static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2766{
2767 struct obj_section *sec;
2768 ElfW(Addr) ofs;
2769
2770 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2771 * If __ksymtab is defined but not marked alloc, x out the first character
2772 * (no obj_delete routine) and create a new __ksymtab with the correct
2773 * characteristics.
2774 */
2775 sec = obj_find_section(f, "__ksymtab");
2776 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2777 *((char *)(sec->name)) = 'x'; /* override const */
2778 sec = NULL;
2779 }
2780 if (!sec)
2781 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002782 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002783 if (!sec)
2784 return;
2785 sec->header.sh_flags |= SHF_ALLOC;
2786 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002787 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002788 ofs = sec->header.sh_size;
2789 obj_symbol_patch(f, sec->idx, ofs, sym);
2790 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2791 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2792}
2793#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002794
2795static int new_create_module_ksymtab(struct obj_file *f)
2796{
2797 struct obj_section *sec;
2798 int i;
2799
2800 /* We must always add the module references. */
2801
2802 if (n_ext_modules_used) {
2803 struct new_module_ref *dep;
2804 struct obj_symbol *tm;
2805
2806 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002807 (sizeof(struct new_module_ref)
2808 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002809 if (!sec)
2810 return 0;
2811
Miles Baderae28b042002-04-01 09:34:25 +00002812 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002813 dep = (struct new_module_ref *) sec->contents;
2814 for (i = 0; i < n_ext_modules; ++i)
2815 if (ext_modules[i].used) {
2816 dep->dep = ext_modules[i].addr;
2817 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002818 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002819 dep->next_ref = 0;
2820 ++dep;
2821 }
2822 }
2823
2824 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2825 size_t nsyms;
2826 int *loaded;
2827
2828 sec =
2829 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002830 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002831
2832 /* We don't want to export symbols residing in sections that
2833 aren't loaded. There are a number of these created so that
2834 we make sure certain module options don't appear twice. */
2835
2836 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2837 while (--i >= 0)
2838 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2839
2840 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2841 struct obj_symbol *sym;
2842 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002843 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002844 && sym->secidx <= SHN_HIRESERVE
2845 && (sym->secidx >= SHN_LORESERVE
2846 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002847 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2848
2849 obj_symbol_patch(f, sec->idx, ofs, sym);
2850 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002851 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002852
2853 nsyms++;
2854 }
2855 }
2856
2857 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2858 }
2859
2860 return 1;
2861}
2862
2863
2864static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002865new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002866{
2867 struct new_module *module;
2868 struct obj_section *sec;
2869 void *image;
2870 int ret;
2871 tgt_long m_addr;
2872
2873 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002874 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002875 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002876 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002877 module = (struct new_module *) sec->contents;
2878 m_addr = sec->header.sh_addr;
2879
2880 module->size_of_struct = sizeof(*module);
2881 module->size = m_size;
2882 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2883
2884 sec = obj_find_section(f, "__ksymtab");
2885 if (sec && sec->header.sh_size) {
2886 module->syms = sec->header.sh_addr;
2887 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2888 }
2889
2890 if (n_ext_modules_used) {
2891 sec = obj_find_section(f, ".kmodtab");
2892 module->deps = sec->header.sh_addr;
2893 module->ndeps = n_ext_modules_used;
2894 }
2895
2896 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002897 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002898 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002899 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002900
2901 sec = obj_find_section(f, "__ex_table");
2902 if (sec) {
2903 module->ex_table_start = sec->header.sh_addr;
2904 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2905 }
2906
2907 sec = obj_find_section(f, ".text.init");
2908 if (sec) {
2909 module->runsize = sec->header.sh_addr - m_addr;
2910 }
2911 sec = obj_find_section(f, ".data.init");
2912 if (sec) {
2913 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002914 module->runsize > sec->header.sh_addr - m_addr)
2915 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002916 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002917 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2918 if (sec && sec->header.sh_size) {
2919 module->archdata_start = (void*)sec->header.sh_addr;
2920 module->archdata_end = module->archdata_start + sec->header.sh_size;
2921 }
2922 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2923 if (sec && sec->header.sh_size) {
2924 module->kallsyms_start = (void*)sec->header.sh_addr;
2925 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2926 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002927
Eric Andersen9f16d612000-06-12 23:11:16 +00002928 /* Whew! All of the initialization is complete. Collect the final
2929 module image and give it to the kernel. */
2930
2931 image = xmalloc(m_size);
2932 obj_create_image(f, image);
2933
Eric Andersencb3b9b12004-06-22 11:50:52 +00002934 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002935 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002936 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002937
2938 free(image);
2939
2940 return ret == 0;
2941}
2942
Eric Andersen9f16d612000-06-12 23:11:16 +00002943
2944/*======================================================================*/
2945
Eric Andersen044228d2001-07-17 01:12:36 +00002946static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002947obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2948 const char *string)
2949{
2950 struct obj_string_patch *p;
2951 struct obj_section *strsec;
2952 size_t len = strlen(string) + 1;
2953 char *loc;
2954
2955 p = xmalloc(sizeof(*p));
2956 p->next = f->string_patches;
2957 p->reloc_secidx = secidx;
2958 p->reloc_offset = offset;
2959 f->string_patches = p;
2960
2961 strsec = obj_find_section(f, ".kstrtab");
2962 if (strsec == NULL) {
2963 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2964 p->string_offset = 0;
2965 loc = strsec->contents;
2966 } else {
2967 p->string_offset = strsec->header.sh_size;
2968 loc = obj_extend_section(strsec, len);
2969 }
2970 memcpy(loc, string, len);
2971
2972 return 1;
2973}
2974
Eric Andersen044228d2001-07-17 01:12:36 +00002975static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002976obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2977 struct obj_symbol *sym)
2978{
2979 struct obj_symbol_patch *p;
2980
2981 p = xmalloc(sizeof(*p));
2982 p->next = f->symbol_patches;
2983 p->reloc_secidx = secidx;
2984 p->reloc_offset = offset;
2985 p->sym = sym;
2986 f->symbol_patches = p;
2987
2988 return 1;
2989}
2990
Eric Andersen044228d2001-07-17 01:12:36 +00002991static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002992{
2993 unsigned long i;
2994 int ret = 1;
2995
2996 for (i = 0; i < HASH_BUCKETS; ++i) {
2997 struct obj_symbol *sym;
2998 for (sym = f->symtab[i]; sym; sym = sym->next)
2999 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003000 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003001 sym->secidx = SHN_ABS;
3002 sym->value = 0;
3003 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003004 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003005 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003006 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003007 ret = 0;
3008 }
3009 }
3010 }
3011
3012 return ret;
3013}
3014
Eric Andersen044228d2001-07-17 01:12:36 +00003015static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003016{
3017 struct common_entry {
3018 struct common_entry *next;
3019 struct obj_symbol *sym;
3020 } *common_head = NULL;
3021
3022 unsigned long i;
3023
3024 for (i = 0; i < HASH_BUCKETS; ++i) {
3025 struct obj_symbol *sym;
3026 for (sym = f->symtab[i]; sym; sym = sym->next)
3027 if (sym->secidx == SHN_COMMON) {
3028 /* Collect all COMMON symbols and sort them by size so as to
3029 minimize space wasted by alignment requirements. */
3030 {
3031 struct common_entry **p, *n;
3032 for (p = &common_head; *p; p = &(*p)->next)
3033 if (sym->size <= (*p)->sym->size)
3034 break;
3035
3036 n = alloca(sizeof(*n));
3037 n->next = *p;
3038 n->sym = sym;
3039 *p = n;
3040 }
3041 }
3042 }
3043
3044 for (i = 1; i < f->local_symtab_size; ++i) {
3045 struct obj_symbol *sym = f->local_symtab[i];
3046 if (sym && sym->secidx == SHN_COMMON) {
3047 struct common_entry **p, *n;
3048 for (p = &common_head; *p; p = &(*p)->next)
3049 if (sym == (*p)->sym)
3050 break;
3051 else if (sym->size < (*p)->sym->size) {
3052 n = alloca(sizeof(*n));
3053 n->next = *p;
3054 n->sym = sym;
3055 *p = n;
3056 break;
3057 }
3058 }
3059 }
3060
3061 if (common_head) {
3062 /* Find the bss section. */
3063 for (i = 0; i < f->header.e_shnum; ++i)
3064 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3065 break;
3066
3067 /* If for some reason there hadn't been one, create one. */
3068 if (i == f->header.e_shnum) {
3069 struct obj_section *sec;
3070
3071 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3072 f->sections[i] = sec = arch_new_section();
3073 f->header.e_shnum = i + 1;
3074
3075 memset(sec, 0, sizeof(*sec));
3076 sec->header.sh_type = SHT_PROGBITS;
3077 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3078 sec->name = ".bss";
3079 sec->idx = i;
3080 }
3081
3082 /* Allocate the COMMONS. */
3083 {
3084 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3085 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3086 struct common_entry *c;
3087
3088 for (c = common_head; c; c = c->next) {
3089 ElfW(Addr) align = c->sym->value;
3090
3091 if (align > max_align)
3092 max_align = align;
3093 if (bss_size & (align - 1))
3094 bss_size = (bss_size | (align - 1)) + 1;
3095
3096 c->sym->secidx = i;
3097 c->sym->value = bss_size;
3098
3099 bss_size += c->sym->size;
3100 }
3101
3102 f->sections[i]->header.sh_size = bss_size;
3103 f->sections[i]->header.sh_addralign = max_align;
3104 }
3105 }
3106
3107 /* For the sake of patch relocation and parameter initialization,
3108 allocate zeroed data for NOBITS sections now. Note that after
3109 this we cannot assume NOBITS are really empty. */
3110 for (i = 0; i < f->header.e_shnum; ++i) {
3111 struct obj_section *s = f->sections[i];
3112 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003113 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003114 s->contents = memset(xmalloc(s->header.sh_size),
3115 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003116 else
3117 s->contents = NULL;
3118
Eric Andersen9f16d612000-06-12 23:11:16 +00003119 s->header.sh_type = SHT_PROGBITS;
3120 }
3121 }
3122}
3123
Eric Andersen044228d2001-07-17 01:12:36 +00003124static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003125{
3126 unsigned long dot = 0;
3127 struct obj_section *sec;
3128
3129 /* Finalize the positions of the sections relative to one another. */
3130
3131 for (sec = f->load_order; sec; sec = sec->load_next) {
3132 ElfW(Addr) align;
3133
3134 align = sec->header.sh_addralign;
3135 if (align && (dot & (align - 1)))
3136 dot = (dot | (align - 1)) + 1;
3137
3138 sec->header.sh_addr = dot;
3139 dot += sec->header.sh_size;
3140 }
3141
3142 return dot;
3143}
3144
Eric Andersen044228d2001-07-17 01:12:36 +00003145static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003146{
3147 int i, n = f->header.e_shnum;
3148 int ret = 1;
3149
3150 /* Finalize the addresses of the sections. */
3151
3152 f->baseaddr = base;
3153 for (i = 0; i < n; ++i)
3154 f->sections[i]->header.sh_addr += base;
3155
3156 /* And iterate over all of the relocations. */
3157
3158 for (i = 0; i < n; ++i) {
3159 struct obj_section *relsec, *symsec, *targsec, *strsec;
3160 ElfW(RelM) * rel, *relend;
3161 ElfW(Sym) * symtab;
3162 const char *strtab;
3163
3164 relsec = f->sections[i];
3165 if (relsec->header.sh_type != SHT_RELM)
3166 continue;
3167
3168 symsec = f->sections[relsec->header.sh_link];
3169 targsec = f->sections[relsec->header.sh_info];
3170 strsec = f->sections[symsec->header.sh_link];
3171
3172 rel = (ElfW(RelM) *) relsec->contents;
3173 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3174 symtab = (ElfW(Sym) *) symsec->contents;
3175 strtab = (const char *) strsec->contents;
3176
3177 for (; rel < relend; ++rel) {
3178 ElfW(Addr) value = 0;
3179 struct obj_symbol *intsym = NULL;
3180 unsigned long symndx;
3181 ElfW(Sym) * extsym = 0;
3182 const char *errmsg;
3183
3184 /* Attempt to find a value to use for this relocation. */
3185
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003186 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003187 if (symndx) {
3188 /* Note we've already checked for undefined symbols. */
3189
3190 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003191 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003192 /* Local symbols we look up in the local table to be sure
3193 we get the one that is really intended. */
3194 intsym = f->local_symtab[symndx];
3195 } else {
3196 /* Others we look up in the hash table. */
3197 const char *name;
3198 if (extsym->st_name)
3199 name = strtab + extsym->st_name;
3200 else
3201 name = f->sections[extsym->st_shndx]->name;
3202 intsym = obj_find_symbol(f, name);
3203 }
3204
3205 value = obj_symbol_final_value(f, intsym);
3206 intsym->referenced = 1;
3207 }
3208#if SHT_RELM == SHT_RELA
3209#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3210 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3211 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003212 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003213#endif
3214 value += rel->r_addend;
3215#endif
3216
3217 /* Do it! */
3218 switch (arch_apply_relocation
3219 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003220 case obj_reloc_ok:
3221 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003222
Eric Andersen3b1a7442003-12-24 20:30:45 +00003223 case obj_reloc_overflow:
3224 errmsg = "Relocation overflow";
3225 goto bad_reloc;
3226 case obj_reloc_dangerous:
3227 errmsg = "Dangerous relocation";
3228 goto bad_reloc;
3229 case obj_reloc_unhandled:
3230 errmsg = "Unhandled relocation";
3231bad_reloc:
3232 if (extsym) {
3233 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003234 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003235 strtab + extsym->st_name);
3236 } else {
3237 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003238 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003239 }
3240 ret = 0;
3241 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003242 }
3243 }
3244 }
3245
3246 /* Finally, take care of the patches. */
3247
3248 if (f->string_patches) {
3249 struct obj_string_patch *p;
3250 struct obj_section *strsec;
3251 ElfW(Addr) strsec_base;
3252 strsec = obj_find_section(f, ".kstrtab");
3253 strsec_base = strsec->header.sh_addr;
3254
3255 for (p = f->string_patches; p; p = p->next) {
3256 struct obj_section *targsec = f->sections[p->reloc_secidx];
3257 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3258 = strsec_base + p->string_offset;
3259 }
3260 }
3261
3262 if (f->symbol_patches) {
3263 struct obj_symbol_patch *p;
3264
3265 for (p = f->symbol_patches; p; p = p->next) {
3266 struct obj_section *targsec = f->sections[p->reloc_secidx];
3267 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3268 = obj_symbol_final_value(f, p->sym);
3269 }
3270 }
3271
3272 return ret;
3273}
3274
Eric Andersen044228d2001-07-17 01:12:36 +00003275static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003276{
3277 struct obj_section *sec;
3278 ElfW(Addr) base = f->baseaddr;
3279
3280 for (sec = f->load_order; sec; sec = sec->load_next) {
3281 char *secimg;
3282
Eric Andersen2bf658d2001-02-24 20:01:53 +00003283 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003284 continue;
3285
3286 secimg = image + (sec->header.sh_addr - base);
3287
3288 /* Note that we allocated data for NOBITS sections earlier. */
3289 memcpy(secimg, sec->contents, sec->header.sh_size);
3290 }
3291
3292 return 1;
3293}
3294
3295/*======================================================================*/
3296
Eric Andersen044228d2001-07-17 01:12:36 +00003297static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003298{
3299 struct obj_file *f;
3300 ElfW(Shdr) * section_headers;
3301 int shnum, i;
3302 char *shstrtab;
3303
3304 /* Read the file header. */
3305
3306 f = arch_new_file();
3307 memset(f, 0, sizeof(*f));
3308 f->symbol_cmp = strcmp;
3309 f->symbol_hash = obj_elf_hash;
3310 f->load_order_search_start = &f->load_order;
3311
3312 fseek(fp, 0, SEEK_SET);
3313 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003314 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003315 return NULL;
3316 }
3317
3318 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003319 || f->header.e_ident[EI_MAG1] != ELFMAG1
3320 || f->header.e_ident[EI_MAG2] != ELFMAG2
3321 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003322 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003323 return NULL;
3324 }
3325 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003326 || f->header.e_ident[EI_DATA] != ELFDATAM
3327 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3328 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003329 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003330 return NULL;
3331 }
3332 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003333 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003334 return NULL;
3335 }
3336
3337 /* Read the section headers. */
3338
3339 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003340 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003341 (unsigned long) f->header.e_shentsize,
3342 (unsigned long) sizeof(ElfW(Shdr)));
3343 return NULL;
3344 }
3345
3346 shnum = f->header.e_shnum;
3347 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3348 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3349
3350 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3351 fseek(fp, f->header.e_shoff, SEEK_SET);
3352 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003353 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003354 return NULL;
3355 }
3356
3357 /* Read the section data. */
3358
3359 for (i = 0; i < shnum; ++i) {
3360 struct obj_section *sec;
3361
3362 f->sections[i] = sec = arch_new_section();
3363 memset(sec, 0, sizeof(*sec));
3364
3365 sec->header = section_headers[i];
3366 sec->idx = i;
3367
Eric Andersen2bf658d2001-02-24 20:01:53 +00003368 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003369 case SHT_NULL:
3370 case SHT_NOTE:
3371 case SHT_NOBITS:
3372 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003373 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003374
3375 case SHT_PROGBITS:
3376#if LOADBITS
3377 if (!loadprogbits) {
3378 sec->contents = NULL;
3379 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003381#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003382 case SHT_SYMTAB:
3383 case SHT_STRTAB:
3384 case SHT_RELM:
3385 if (sec->header.sh_size > 0) {
3386 sec->contents = xmalloc(sec->header.sh_size);
3387 fseek(fp, sec->header.sh_offset, SEEK_SET);
3388 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3389 bb_perror_msg("error reading ELF section data");
3390 return NULL;
3391 }
3392 } else {
3393 sec->contents = NULL;
3394 }
3395 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003396
3397#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003398 case SHT_RELA:
3399 bb_error_msg("RELA relocations not supported on this architecture");
3400 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003401#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003402 case SHT_REL:
3403 bb_error_msg("REL relocations not supported on this architecture");
3404 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003405#endif
3406
Eric Andersen3b1a7442003-12-24 20:30:45 +00003407 default:
3408 if (sec->header.sh_type >= SHT_LOPROC) {
3409 /* Assume processor specific section types are debug
3410 info and can safely be ignored. If this is ever not
3411 the case (Hello MIPS?), don't put ifdefs here but
3412 create an arch_load_proc_section(). */
3413 break;
3414 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003415
Eric Andersen3b1a7442003-12-24 20:30:45 +00003416 bb_error_msg("can't handle sections of type %ld",
3417 (long) sec->header.sh_type);
3418 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003419 }
3420 }
3421
3422 /* Do what sort of interpretation as needed by each section. */
3423
3424 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3425
3426 for (i = 0; i < shnum; ++i) {
3427 struct obj_section *sec = f->sections[i];
3428 sec->name = shstrtab + sec->header.sh_name;
3429 }
3430
3431 for (i = 0; i < shnum; ++i) {
3432 struct obj_section *sec = f->sections[i];
3433
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003434 /* .modinfo should be contents only but gcc has no attribute for that.
3435 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3436 */
3437 if (strcmp(sec->name, ".modinfo") == 0)
3438 sec->header.sh_flags &= ~SHF_ALLOC;
3439
Eric Andersen9f16d612000-06-12 23:11:16 +00003440 if (sec->header.sh_flags & SHF_ALLOC)
3441 obj_insert_section_load_order(f, sec);
3442
3443 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003444 case SHT_SYMTAB:
3445 {
3446 unsigned long nsym, j;
3447 char *strtab;
3448 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003449
Eric Andersen3b1a7442003-12-24 20:30:45 +00003450 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3451 bb_error_msg("symbol size mismatch: %lu != %lu",
3452 (unsigned long) sec->header.sh_entsize,
3453 (unsigned long) sizeof(ElfW(Sym)));
3454 return NULL;
3455 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003456
Eric Andersen3b1a7442003-12-24 20:30:45 +00003457 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3458 strtab = f->sections[sec->header.sh_link]->contents;
3459 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003460
Eric Andersen3b1a7442003-12-24 20:30:45 +00003461 /* Allocate space for a table of local symbols. */
3462 j = f->local_symtab_size = sec->header.sh_info;
3463 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003464
Eric Andersen3b1a7442003-12-24 20:30:45 +00003465 /* Insert all symbols into the hash table. */
3466 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3467 ElfW(Addr) val = sym->st_value;
3468 const char *name;
3469 if (sym->st_name)
3470 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003471 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003472 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003473 else
3474 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003475
Eric Andersenbf833552003-08-13 19:56:33 +00003476#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003477 /*
3478 * For sh64 it is possible that the target of a branch
3479 * requires a mode switch (32 to 16 and back again).
3480 *
3481 * This is implied by the lsb being set in the target
3482 * address for SHmedia mode and clear for SHcompact.
3483 */
3484 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003485#endif
3486
Eric Andersen3b1a7442003-12-24 20:30:45 +00003487 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3488 val, sym->st_size);
3489 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003490 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003491 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003492
Eric Andersen3b1a7442003-12-24 20:30:45 +00003493 case SHT_RELM:
3494 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3495 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3496 (unsigned long) sec->header.sh_entsize,
3497 (unsigned long) sizeof(ElfW(RelM)));
3498 return NULL;
3499 }
3500 break;
3501 /* XXX Relocation code from modutils-2.3.19 is not here.
3502 * Why? That's about 20 lines of code from obj/obj_load.c,
3503 * which gets done in a second pass through the sections.
3504 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003505 }
3506 }
3507
3508 return f;
3509}
3510
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003511#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003512/*
3513 * load the unloaded sections directly into the memory allocated by
3514 * kernel for the module
3515 */
3516
Eric Andersenac5dbd12001-08-22 05:26:08 +00003517static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003518{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003519 ElfW(Addr) base = f->baseaddr;
3520 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003521
Eric Andersen8ae319a2001-05-21 16:09:18 +00003522 for (sec = f->load_order; sec; sec = sec->load_next) {
3523
3524 /* section already loaded? */
3525 if (sec->contents != NULL)
3526 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003527
Eric Andersen8ae319a2001-05-21 16:09:18 +00003528 if (sec->header.sh_size == 0)
3529 continue;
3530
3531 sec->contents = imagebase + (sec->header.sh_addr - base);
3532 fseek(fp, sec->header.sh_offset, SEEK_SET);
3533 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003534 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003535 return 0;
3536 }
3537
3538 }
3539 return 1;
3540}
3541#endif
3542
Eric Andersen9f16d612000-06-12 23:11:16 +00003543static void hide_special_symbols(struct obj_file *f)
3544{
3545 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003546 SPFX "cleanup_module",
3547 SPFX "init_module",
3548 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003549 NULL
3550 };
3551
3552 struct obj_symbol *sym;
3553 const char *const *p;
3554
3555 for (p = specials; *p; ++p)
3556 if ((sym = obj_find_symbol(f, *p)) != NULL)
3557 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003558 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003559}
3560
Glenn L McGrath759515c2003-08-30 06:00:33 +00003561
Eric Andersen71ae64b2002-10-10 04:20:21 +00003562#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003563static int obj_gpl_license(struct obj_file *f, const char **license)
3564{
3565 struct obj_section *sec;
3566 /* This list must match *exactly* the list of allowable licenses in
3567 * linux/include/linux/module.h. Checking for leading "GPL" will not
3568 * work, somebody will use "GPL sucks, this is proprietary".
3569 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003570 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003571 "GPL",
3572 "GPL v2",
3573 "GPL and additional rights",
3574 "Dual BSD/GPL",
3575 "Dual MPL/GPL",
3576 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003577
Eric Andersen166fa462002-09-16 05:30:24 +00003578 if ((sec = obj_find_section(f, ".modinfo"))) {
3579 const char *value, *ptr, *endptr;
3580 ptr = sec->contents;
3581 endptr = ptr + sec->header.sh_size;
3582 while (ptr < endptr) {
3583 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3584 int i;
3585 if (license)
3586 *license = value+1;
3587 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3588 if (strcmp(value+1, gpl_licenses[i]) == 0)
3589 return(0);
3590 }
3591 return(2);
3592 }
3593 if (strchr(ptr, '\0'))
3594 ptr = strchr(ptr, '\0') + 1;
3595 else
3596 ptr = endptr;
3597 }
3598 }
3599 return(1);
3600}
3601
3602#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3603#define TAINT_PROPRIETORY_MODULE (1<<0)
3604#define TAINT_FORCED_MODULE (1<<1)
3605#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003606#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003607
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003608static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003609 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3610{
3611 char buf[80];
3612 int oldval;
3613 static int first = 1;
3614 if (fd < 0 && !kernel_has_tainted)
3615 return; /* New modutils on old kernel */
3616 printf("Warning: loading %s will taint the kernel: %s%s\n",
3617 m_name, text1, text2);
3618 if (first) {
3619 printf(" See %s for information about tainted modules\n", TAINT_URL);
3620 first = 0;
3621 }
3622 if (fd >= 0) {
3623 read(fd, buf, sizeof(buf)-1);
3624 buf[sizeof(buf)-1] = '\0';
3625 oldval = strtoul(buf, NULL, 10);
3626 sprintf(buf, "%d\n", oldval | taint);
3627 write(fd, buf, strlen(buf));
3628 }
3629}
3630
3631/* Check if loading this module will taint the kernel. */
3632static void check_tainted_module(struct obj_file *f, char *m_name)
3633{
3634 static const char tainted_file[] = TAINT_FILENAME;
3635 int fd, kernel_has_tainted;
3636 const char *ptr;
3637
3638 kernel_has_tainted = 1;
3639 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3640 if (errno == ENOENT)
3641 kernel_has_tainted = 0;
3642 else if (errno == EACCES)
3643 kernel_has_tainted = 1;
3644 else {
3645 perror(tainted_file);
3646 kernel_has_tainted = 0;
3647 }
3648 }
3649
3650 switch (obj_gpl_license(f, &ptr)) {
3651 case 0:
3652 break;
3653 case 1:
3654 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3655 break;
3656 case 2:
3657 /* The module has a non-GPL license so we pretend that the
3658 * kernel always has a taint flag to get a warning even on
3659 * kernels without the proc flag.
3660 */
3661 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3662 break;
3663 default:
3664 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3665 break;
3666 }
3667
3668 if (flag_force_load)
3669 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3670
3671 if (fd >= 0)
3672 close(fd);
3673}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003674#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3675#define check_tainted_module(x, y) do { } while(0);
3676#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003677
Eric Andersen889dd202003-01-23 04:48:34 +00003678#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3679/* add module source, timestamp, kernel version and a symbol for the
3680 * start of some sections. this info is used by ksymoops to do better
3681 * debugging.
3682 */
3683static int
3684get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3685{
3686#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003687 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003688#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003689 strncpy(str, "???", sizeof(str));
3690 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003691#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3692}
3693
3694/* add module source, timestamp, kernel version and a symbol for the
3695 * start of some sections. this info is used by ksymoops to do better
3696 * debugging.
3697 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003698static void
Eric Andersen889dd202003-01-23 04:48:34 +00003699add_ksymoops_symbols(struct obj_file *f, const char *filename,
3700 const char *m_name)
3701{
3702 static const char symprefix[] = "__insmod_";
3703 struct obj_section *sec;
3704 struct obj_symbol *sym;
3705 char *name, *absolute_filename;
3706 char str[STRVERSIONLEN], real[PATH_MAX];
3707 int i, l, lm_name, lfilename, use_ksymtab, version;
3708 struct stat statbuf;
3709
3710 static const char *section_names[] = {
3711 ".text",
3712 ".rodata",
3713 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003714 ".bss",
3715 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003716 };
3717
3718 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003719 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003720 }
3721 else {
3722 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003723 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003724 errno = save_errno;
3725 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003726 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003727 }
3728
3729 lm_name = strlen(m_name);
3730 lfilename = strlen(absolute_filename);
3731
3732 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3733 * are not to be exported. otherwise leave ksymtab alone for now, the
3734 * "export all symbols" compatibility code will export these symbols later.
3735 */
3736 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3737
3738 if ((sec = obj_find_section(f, ".this"))) {
3739 /* tag the module header with the object name, last modified
3740 * timestamp and module version. worst case for module version
3741 * is 0xffffff, decimal 16777215. putting all three fields in
3742 * one symbol is less readable but saves kernel space.
3743 */
3744 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003745 lm_name+ /* module name */
3746 2+ /* "_O" */
3747 lfilename+ /* object filename */
3748 2+ /* "_M" */
3749 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3750 2+ /* "_V" */
3751 8+ /* version in dec */
3752 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003753 name = xmalloc(l);
3754 if (stat(absolute_filename, &statbuf) != 0)
3755 statbuf.st_mtime = 0;
3756 version = get_module_version(f, str); /* -1 if not found */
3757 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003758 symprefix, m_name, absolute_filename,
3759 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3760 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003761 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003762 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003763 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003764 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003765 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003766 }
3767 free(absolute_filename);
3768#ifdef _NOT_SUPPORTED_
3769 /* record where the persistent data is going, same address as previous symbol */
3770
3771 if (f->persist) {
3772 l = sizeof(symprefix)+ /* "__insmod_" */
3773 lm_name+ /* module name */
3774 2+ /* "_P" */
3775 strlen(f->persist)+ /* data store */
3776 1; /* nul */
3777 name = xmalloc(l);
3778 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003779 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003780 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003781 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003782 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003783 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003784 }
3785#endif /* _NOT_SUPPORTED_ */
3786 /* tag the desired sections if size is non-zero */
3787
3788 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3789 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003790 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003791 l = sizeof(symprefix)+ /* "__insmod_" */
3792 lm_name+ /* module name */
3793 2+ /* "_S" */
3794 strlen(sec->name)+ /* section name */
3795 2+ /* "_L" */
3796 8+ /* length in dec */
3797 1; /* nul */
3798 name = xmalloc(l);
3799 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003800 symprefix, m_name, sec->name,
3801 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003802 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003803 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003804 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003805 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003806 }
3807 }
3808}
3809#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3810
Eric Andersenbe65c352003-01-23 04:57:35 +00003811#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3812static void print_load_map(struct obj_file *f)
3813{
3814 struct obj_symbol *sym;
3815 struct obj_symbol **all, **p;
3816 struct obj_section *sec;
3817 int i, nsyms, *loaded;
3818
3819 /* Report on the section layout. */
3820
3821 printf("Sections: Size %-*s Align\n",
3822 (int) (2 * sizeof(void *)), "Address");
3823
3824 for (sec = f->load_order; sec; sec = sec->load_next) {
3825 int a;
3826 unsigned long tmp;
3827
3828 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3829 tmp >>= 1;
3830 if (a == -1)
3831 a = 0;
3832
3833 printf("%-15s %08lx %0*lx 2**%d\n",
3834 sec->name,
3835 (long)sec->header.sh_size,
3836 (int) (2 * sizeof(void *)),
3837 (long)sec->header.sh_addr,
3838 a);
3839 }
3840#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3841 /* Quick reference which section indicies are loaded. */
3842
3843 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3844 while (--i >= 0)
3845 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3846
3847 /* Collect the symbols we'll be listing. */
3848
3849 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3850 for (sym = f->symtab[i]; sym; sym = sym->next)
3851 if (sym->secidx <= SHN_HIRESERVE
3852 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3853 ++nsyms;
3854
3855 all = alloca(nsyms * sizeof(struct obj_symbol *));
3856
3857 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3858 for (sym = f->symtab[i]; sym; sym = sym->next)
3859 if (sym->secidx <= SHN_HIRESERVE
3860 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3861 *p++ = sym;
3862
3863 /* And list them. */
3864 printf("\nSymbols:\n");
3865 for (p = all; p < all + nsyms; ++p) {
3866 char type = '?';
3867 unsigned long value;
3868
3869 sym = *p;
3870 if (sym->secidx == SHN_ABS) {
3871 type = 'A';
3872 value = sym->value;
3873 } else if (sym->secidx == SHN_UNDEF) {
3874 type = 'U';
3875 value = 0;
3876 } else {
3877 sec = f->sections[sym->secidx];
3878
3879 if (sec->header.sh_type == SHT_NOBITS)
3880 type = 'B';
3881 else if (sec->header.sh_flags & SHF_ALLOC) {
3882 if (sec->header.sh_flags & SHF_EXECINSTR)
3883 type = 'T';
3884 else if (sec->header.sh_flags & SHF_WRITE)
3885 type = 'D';
3886 else
3887 type = 'R';
3888 }
3889 value = sym->value + sec->header.sh_addr;
3890 }
3891
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003892 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003893 type = tolower(type);
3894
3895 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3896 type, sym->name);
3897 }
3898#endif
3899}
3900
3901#endif
3902
Eric Andersen9f16d612000-06-12 23:11:16 +00003903extern int insmod_main( int argc, char **argv)
3904{
Eric Andersena18aaf12001-01-24 19:07:09 +00003905 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003906 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003907 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003908 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003909 unsigned long m_size;
3910 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003911 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003912 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003913 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003914 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003915 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003916#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003917 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003919 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003920#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003921#ifdef CONFIG_FEATURE_CLEAN_UP
3922 FILE *fp = 0;
3923#else
3924 FILE *fp;
3925#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003926#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3927 int flag_print_load_map = 0;
3928#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003929 int k_version = 0;
3930 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003931
Erik Andersene49d5ec2000-02-08 19:58:47 +00003932 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003933#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003934 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003935#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003936 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003937#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003938 {
3939 switch (opt) {
3940 case 'f': /* force loading */
3941 flag_force_load = 1;
3942 break;
3943 case 'k': /* module loaded by kerneld, auto-cleanable */
3944 flag_autoclean = 1;
3945 break;
3946 case 's': /* log to syslog */
3947 /* log to syslog -- not supported */
3948 /* but kernel needs this for request_module(), */
3949 /* as this calls: modprobe -k -s -- <module> */
3950 /* so silently ignore this flag */
3951 break;
3952 case 'v': /* verbose output */
3953 flag_verbose = 1;
3954 break;
3955 case 'q': /* silent */
3956 flag_quiet = 1;
3957 break;
3958 case 'x': /* do not export externs */
3959 flag_export = 0;
3960 break;
3961 case 'o': /* name the output module */
3962 free(m_name);
3963 m_name = bb_xstrdup(optarg);
3964 break;
3965 case 'L': /* Stub warning */
3966 /* This is needed for compatibility with modprobe.
3967 * In theory, this does locking, but we don't do
3968 * that. So be careful and plan your life around not
3969 * loading the same module 50 times concurrently. */
3970 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003971#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003972 case 'm': /* print module load map */
3973 flag_print_load_map = 1;
3974 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003975#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003976 default:
3977 bb_show_usage();
3978 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003979 }
Eric Andersen03d80912003-12-19 21:04:19 +00003980
Eric Andersena18aaf12001-01-24 19:07:09 +00003981 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003982 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003983 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003984
Erik Andersene49d5ec2000-02-08 19:58:47 +00003985 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003986 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003987 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003988 len = strlen(tmp);
3989
Eric Andersen03d80912003-12-19 21:04:19 +00003990 if (uname(&myuname) == 0) {
3991 if (myuname.release[0] == '2') {
3992 k_version = myuname.release[2] - '0';
3993 }
3994 }
3995
3996#if defined(CONFIG_FEATURE_2_6_MODULES)
3997 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003998 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003999 len-=3;
4000 tmp[len] = '\0';
4001 }
4002 else
4003#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004004 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4005 len-=2;
4006 tmp[len] = '\0';
4007 }
Eric Andersen2d342152002-06-18 05:16:25 +00004008
Eric Andersen03d80912003-12-19 21:04:19 +00004009
4010#if defined(CONFIG_FEATURE_2_6_MODULES)
4011 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004012 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004013 else
Eric Andersen03d80912003-12-19 21:04:19 +00004014#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004015 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004016
Eric Andersen61f83052002-06-22 17:15:42 +00004017 if (!m_name) {
4018 m_name = tmp;
4019 } else {
4020 free(tmp1);
4021 tmp1 = 0; /* flag for free(m_name) before exit() */
4022 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004023
Eric Andersen14d35432001-05-14 17:07:32 +00004024 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004025 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4026 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004027 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4028 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004029 if (k_version) { /* uname succeedd */
4030 char *module_dir;
4031 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004032 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004033
Eric Andersen03d80912003-12-19 21:04:19 +00004034 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004035 /* Jump through hoops in case /lib/modules/`uname -r`
4036 * is a symlink. We do not want recursive_action to
4037 * follow symlinks, but we do want to follow the
4038 * /lib/modules/`uname -r` dir, So resolve it ourselves
4039 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004040 if (realpath (tmdn, real_module_dir) == NULL)
4041 module_dir = tmdn;
4042 else
4043 module_dir = real_module_dir;
4044 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004045 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004046 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004047 }
4048
4049 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004050 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004051 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004052 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004053
Eric Andersen03d80912003-12-19 21:04:19 +00004054 free(m_filename);
4055 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004056 if (realpath (_PATH_MODULES, module_dir) == NULL)
4057 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004058 /* No module found under /lib/modules/`uname -r`, this
4059 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004060 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004061 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004062 {
Eric Andersen61f83052002-06-22 17:15:42 +00004063 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004064 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004065 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004066 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004067 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004068 }
4069 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004070 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004071 }
Eric Andersen03d80912003-12-19 21:04:19 +00004072 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004073 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004074
Rob Landley999af202005-12-11 20:14:12 +00004075 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004076 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004077
Eric Andersene7047882003-12-11 01:42:13 +00004078#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004079 if (k_version > 4)
4080 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004081 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004082 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004083 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004084 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004085#endif
4086
Eric Andersen8ae319a2001-05-21 16:09:18 +00004087 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004088 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004089
Eric Andersen9f16d612000-06-12 23:11:16 +00004090 if (get_modinfo_value(f, "kernel_version") == NULL)
4091 m_has_modinfo = 0;
4092 else
4093 m_has_modinfo = 1;
4094
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004095#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004096 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004097 if (!flag_quiet) {
4098 if (uname(&uts_info) < 0)
4099 uts_info.release[0] = '\0';
4100 if (m_has_modinfo) {
4101 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004102 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004103 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004104 "compiled for");
4105 goto out;
4106 }
4107 }
4108
4109 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4110 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004111 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004112 "\t%s was compiled for kernel version %s\n"
4113 "\twhile this kernel is version %s",
4114 m_filename, m_strversion, uts_info.release);
4115 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004116 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004117 "\t%s was compiled for kernel version %s\n"
4118 "\twhile this kernel is version %s.",
4119 m_filename, m_strversion, uts_info.release);
4120 goto out;
4121 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004122 }
4123 }
4124 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004125#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004126
Eric Andersencb3b9b12004-06-22 11:50:52 +00004127 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004128 if (!new_get_kernel_symbols())
4129 goto out;
4130 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004131 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004132 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004133 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004134 }
4135
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004136#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004137 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 if (m_has_modinfo)
4139 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004140
4141 if (m_crcs != k_crcs)
4142 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004143#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004144
Erik Andersene49d5ec2000-02-08 19:58:47 +00004145 /* Let the module know about the kernel symbols. */
4146 add_kernel_symbols(f);
4147
Eric Andersen9f16d612000-06-12 23:11:16 +00004148 /* Allocate common symbols, symbol tables, and string tables. */
4149
Eric Andersencb3b9b12004-06-22 11:50:52 +00004150 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004151 {
4152 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004153 }
4154
Eric Andersen9f16d612000-06-12 23:11:16 +00004155 if (!obj_check_undefineds(f)) {
4156 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004157 }
4158 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004159 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004160
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004161 /* done with the module name, on to the optional var=value arguments */
4162 ++optind;
4163
Eric Andersen9f16d612000-06-12 23:11:16 +00004164 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004165 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004166 {
4167 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004168 }
4169 }
4170
Eric Andersen9f16d612000-06-12 23:11:16 +00004171 arch_create_got(f);
4172 hide_special_symbols(f);
4173
Eric Andersen889dd202003-01-23 04:48:34 +00004174#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4175 add_ksymoops_symbols(f, m_filename, m_name);
4176#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4177
Eric Andersencb3b9b12004-06-22 11:50:52 +00004178 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004179
Erik Andersene49d5ec2000-02-08 19:58:47 +00004180 /* Find current size of the module */
4181 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004182
4183
Erik Andersene49d5ec2000-02-08 19:58:47 +00004184 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004185 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004186 case EEXIST:
4187 bb_error_msg("A module named %s already exists", m_name);
4188 goto out;
4189 case ENOMEM:
4190 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4191 m_size);
4192 goto out;
4193 default:
4194 bb_perror_msg("create_module: %s", m_name);
4195 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004196 }
Erik Andersend387d011999-12-21 02:55:11 +00004197
Eric Andersen8ae319a2001-05-21 16:09:18 +00004198#if !LOADBITS
4199 /*
4200 * the PROGBITS section was not loaded by the obj_load
4201 * now we can load them directly into the kernel memory
4202 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004203 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004204 delete_module(m_name);
4205 goto out;
4206 }
Eric Andersen03d80912003-12-19 21:04:19 +00004207#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004208
Eric Andersen9f16d612000-06-12 23:11:16 +00004209 if (!obj_relocate(f, m_addr)) {
4210 delete_module(m_name);
4211 goto out;
4212 }
Erik Andersend387d011999-12-21 02:55:11 +00004213
Eric Andersencb3b9b12004-06-22 11:50:52 +00004214 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004215 {
4216 delete_module(m_name);
4217 goto out;
4218 }
4219
Eric Andersenbe65c352003-01-23 04:57:35 +00004220#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4221 if(flag_print_load_map)
4222 print_load_map(f);
4223#endif
4224
Matt Kraai3e856ce2000-12-01 02:55:13 +00004225 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004226
4227out:
Eric Andersen61f83052002-06-22 17:15:42 +00004228#ifdef CONFIG_FEATURE_CLEAN_UP
4229 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004230 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004231 if(tmp1) {
4232 free(tmp1);
4233 } else {
4234 free(m_name);
4235 }
4236 free(m_filename);
4237#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004238 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004239}
Eric Andersene7047882003-12-11 01:42:13 +00004240
4241
4242#endif
4243
4244
4245#ifdef CONFIG_FEATURE_2_6_MODULES
4246
4247#include <sys/mman.h>
4248#include <asm/unistd.h>
4249#include <sys/syscall.h>
4250
4251/* We use error numbers in a loose translation... */
4252static const char *moderror(int err)
4253{
4254 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004255 case ENOEXEC:
4256 return "Invalid module format";
4257 case ENOENT:
4258 return "Unknown symbol in module";
4259 case ESRCH:
4260 return "Module has wrong symbol version";
4261 case EINVAL:
4262 return "Invalid parameters";
4263 default:
4264 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004265 }
4266}
4267
4268extern int insmod_ng_main( int argc, char **argv)
4269{
4270 int i;
4271 int fd;
4272 long int ret;
4273 struct stat st;
4274 unsigned long len;
4275 void *map;
4276 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004277
Eric Andersene7047882003-12-11 01:42:13 +00004278 filename = argv[1];
4279 if (!filename) {
4280 bb_show_usage();
4281 return -1;
4282 }
4283
4284 /* Rest is options */
4285 for (i = 2; i < argc; i++) {
4286 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4287 /* Spaces handled by "" pairs, but no way of escaping quotes */
4288 if (strchr(argv[i], ' ')) {
4289 strcat(options, "\"");
4290 strcat(options, argv[i]);
4291 strcat(options, "\"");
4292 } else {
4293 strcat(options, argv[i]);
4294 }
4295 strcat(options, " ");
4296 }
4297
4298 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4299 bb_perror_msg_and_die("cannot open module `%s'", filename);
4300 }
4301
4302 fstat(fd, &st);
4303 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004304 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004305 if (map == MAP_FAILED) {
4306 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4307 }
4308
4309 ret = syscall(__NR_init_module, map, len, options);
4310 if (ret != 0) {
4311 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004312 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004313 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314
Eric Andersene7047882003-12-11 01:42:13 +00004315 return 0;
4316}
4317
4318#endif