blob: 79bdebd2c2b156bf5580f3cefbe450dd37b258e2 [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 */
298#define EM_CYGNUS_V850 0x9080
299#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
698#define SPFX ""
699#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 Andersenbdfd0d72001-10-24 05:00:29 +0000863#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000864 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000865#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000866#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000867 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000868 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000869# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000870 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000871# else
Eric Andersencffd5022002-05-24 06:50:15 +0000872 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000873# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000874#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000875
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000876 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000877
Eric Andersencffd5022002-05-24 06:50:15 +0000878#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000879
Eric Andersen3b1a7442003-12-24 20:30:45 +0000880 case R_ARM_NONE:
881 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000882
Eric Andersen3b1a7442003-12-24 20:30:45 +0000883 case R_ARM_ABS32:
884 *loc += v;
885 break;
Miles Baderae28b042002-04-01 09:34:25 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_GOT32:
888 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000889
Eric Andersen3b1a7442003-12-24 20:30:45 +0000890 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000891 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
892 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000893 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 assert(got);
896 *loc += got - dot;
897 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000898
Eric Andersen3b1a7442003-12-24 20:30:45 +0000899 case R_ARM_PC24:
900 case R_ARM_PLT32:
901 goto bb_use_plt;
902
903 case R_ARM_GOTOFF: /* address relative to the got */
904 assert(got);
905 *loc += v - got;
906 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000907
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000908#elif defined(__cris__)
909
910 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000911 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000912
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000913 case R_CRIS_32:
914 /* CRIS keeps the relocation value in the r_addend field and
915 * should not use whats in *loc at all
916 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000917 *loc = v;
918 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000919
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000920#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000921
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000922 case R_H8_DIR24R8:
923 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
924 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000925 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000926 case R_H8_DIR24A8:
927 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000928 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000929 case R_H8_DIR32:
930 case R_H8_DIR32A16:
931 *loc += v;
932 break;
933 case R_H8_PCREL16:
934 v -= dot + 2;
935 if ((ElfW(Sword))v > 0x7fff ||
936 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
937 ret = obj_reloc_overflow;
938 else
939 *(unsigned short *)loc = v;
940 break;
941 case R_H8_PCREL8:
942 v -= dot + 1;
943 if ((ElfW(Sword))v > 0x7f ||
944 (ElfW(Sword))v < -(ElfW(Sword))0x80)
945 ret = obj_reloc_overflow;
946 else
947 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000949
Eric Andersencffd5022002-05-24 06:50:15 +0000950#elif defined(__i386__)
951
Eric Andersen3b1a7442003-12-24 20:30:45 +0000952 case R_386_NONE:
953 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000954
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 case R_386_32:
956 *loc += v;
957 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000958
Eric Andersen3b1a7442003-12-24 20:30:45 +0000959 case R_386_PLT32:
960 case R_386_PC32:
961 *loc += v - dot;
962 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000963
Eric Andersen3b1a7442003-12-24 20:30:45 +0000964 case R_386_GLOB_DAT:
965 case R_386_JMP_SLOT:
966 *loc = v;
967 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_RELATIVE:
970 *loc += f->baseaddr;
971 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000972
Eric Andersen3b1a7442003-12-24 20:30:45 +0000973 case R_386_GOTPC:
974 assert(got != 0);
975 *loc += got - dot;
976 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000977
Eric Andersen3b1a7442003-12-24 20:30:45 +0000978 case R_386_GOT32:
979 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000980
Eric Andersen3b1a7442003-12-24 20:30:45 +0000981 case R_386_GOTOFF:
982 assert(got != 0);
983 *loc += v - got;
984 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000985
986#elif defined(__mc68000__)
987
Eric Andersen3b1a7442003-12-24 20:30:45 +0000988 case R_68K_NONE:
989 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000990
Eric Andersen3b1a7442003-12-24 20:30:45 +0000991 case R_68K_32:
992 *loc += v;
993 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000994
Eric Andersen3b1a7442003-12-24 20:30:45 +0000995 case R_68K_8:
996 if (v > 0xff) {
997 ret = obj_reloc_overflow;
998 }
999 *(char *)loc = v;
1000 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001001
Eric Andersen3b1a7442003-12-24 20:30:45 +00001002 case R_68K_16:
1003 if (v > 0xffff) {
1004 ret = obj_reloc_overflow;
1005 }
1006 *(short *)loc = v;
1007 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001008
Eric Andersen3b1a7442003-12-24 20:30:45 +00001009 case R_68K_PC8:
1010 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001011 if ((ElfW(Sword))v > 0x7f ||
1012 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001013 ret = obj_reloc_overflow;
1014 }
1015 *(char *)loc = v;
1016 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001017
Eric Andersen3b1a7442003-12-24 20:30:45 +00001018 case R_68K_PC16:
1019 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001020 if ((ElfW(Sword))v > 0x7fff ||
1021 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001022 ret = obj_reloc_overflow;
1023 }
1024 *(short *)loc = v;
1025 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001026
Eric Andersen3b1a7442003-12-24 20:30:45 +00001027 case R_68K_PC32:
1028 *(int *)loc = v - dot;
1029 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001030
Eric Andersen3b1a7442003-12-24 20:30:45 +00001031 case R_68K_GLOB_DAT:
1032 case R_68K_JMP_SLOT:
1033 *loc = v;
1034 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001035
Eric Andersen3b1a7442003-12-24 20:30:45 +00001036 case R_68K_RELATIVE:
1037 *(int *)loc += f->baseaddr;
1038 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001039
Eric Andersen3b1a7442003-12-24 20:30:45 +00001040 case R_68K_GOT32:
1041 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001042
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001043# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001044 case R_68K_GOTOFF:
1045 assert(got != 0);
1046 *loc += v - got;
1047 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001048# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001049
1050#elif defined(__mips__)
1051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_MIPS_NONE:
1053 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001054
Eric Andersen3b1a7442003-12-24 20:30:45 +00001055 case R_MIPS_32:
1056 *loc += v;
1057 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001058
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 case R_MIPS_26:
1060 if (v % 4)
1061 ret = obj_reloc_dangerous;
1062 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1063 ret = obj_reloc_overflow;
1064 *loc =
1065 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1066 0x03ffffff);
1067 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001068
Eric Andersen3b1a7442003-12-24 20:30:45 +00001069 case R_MIPS_HI16:
1070 {
1071 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001072
Eric Andersen3b1a7442003-12-24 20:30:45 +00001073 /* We cannot relocate this one now because we don't know the value
1074 of the carry we need to add. Save the information, and let LO16
1075 do the actual relocation. */
1076 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1077 n->addr = loc;
1078 n->value = v;
1079 n->next = ifile->mips_hi16_list;
1080 ifile->mips_hi16_list = n;
1081 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001082 }
1083
Eric Andersen3b1a7442003-12-24 20:30:45 +00001084 case R_MIPS_LO16:
1085 {
1086 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001087 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001088
1089 /* Sign extend the addend we extract from the lo insn. */
1090 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1091
1092 if (ifile->mips_hi16_list != NULL) {
1093 struct mips_hi16 *l;
1094
1095 l = ifile->mips_hi16_list;
1096 while (l != NULL) {
1097 struct mips_hi16 *next;
1098 unsigned long insn;
1099
1100 /* The value for the HI16 had best be the same. */
1101 assert(v == l->value);
1102
1103 /* Do the HI16 relocation. Note that we actually don't
1104 need to know anything about the LO16 itself, except where
1105 to find the low 16 bits of the addend needed by the LO16. */
1106 insn = *l->addr;
1107 val =
1108 ((insn & 0xffff) << 16) +
1109 vallo;
1110 val += v;
1111
1112 /* Account for the sign extension that will happen in the
1113 low bits. */
1114 val =
1115 ((val >> 16) +
1116 ((val & 0x8000) !=
1117 0)) & 0xffff;
1118
1119 insn = (insn & ~0xffff) | val;
1120 *l->addr = insn;
1121
1122 next = l->next;
1123 free(l);
1124 l = next;
1125 }
1126
1127 ifile->mips_hi16_list = NULL;
1128 }
1129
1130 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1131 val = v + vallo;
1132 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1133 *loc = insnlo;
1134 break;
1135 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001136
Mike Frysingerf982d862006-01-04 00:11:26 +00001137#elif defined(__nios2__)
1138
1139 case R_NIOS2_NONE:
1140 break;
1141
1142 case R_NIOS2_BFD_RELOC_32:
1143 *loc += v;
1144 break;
1145
1146 case R_NIOS2_BFD_RELOC_16:
1147 if (v > 0xffff) {
1148 ret = obj_reloc_overflow;
1149 }
1150 *(short *)loc = v;
1151 break;
1152
1153 case R_NIOS2_BFD_RELOC_8:
1154 if (v > 0xff) {
1155 ret = obj_reloc_overflow;
1156 }
1157 *(char *)loc = v;
1158 break;
1159
1160 case R_NIOS2_S16:
1161 {
1162 Elf32_Addr word;
1163
1164 if ((Elf32_Sword)v > 0x7fff ||
1165 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1166 ret = obj_reloc_overflow;
1167 }
1168
1169 word = *loc;
1170 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1171 (word & 0x3f);
1172 }
1173 break;
1174
1175 case R_NIOS2_U16:
1176 {
1177 Elf32_Addr word;
1178
1179 if (v > 0xffff) {
1180 ret = obj_reloc_overflow;
1181 }
1182
1183 word = *loc;
1184 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1185 (word & 0x3f);
1186 }
1187 break;
1188
1189 case R_NIOS2_PCREL16:
1190 {
1191 Elf32_Addr word;
1192
1193 v -= dot + 4;
1194 if ((Elf32_Sword)v > 0x7fff ||
1195 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1196 ret = obj_reloc_overflow;
1197 }
1198
1199 word = *loc;
1200 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1201 }
1202 break;
1203
1204 case R_NIOS2_GPREL:
1205 {
1206 Elf32_Addr word, gp;
1207 /* get _gp */
1208 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1209 v-=gp;
1210 if ((Elf32_Sword)v > 0x7fff ||
1211 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1212 ret = obj_reloc_overflow;
1213 }
1214
1215 word = *loc;
1216 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1217 }
1218 break;
1219
1220 case R_NIOS2_CALL26:
1221 if (v & 3)
1222 ret = obj_reloc_dangerous;
1223 if ((v >> 28) != (dot >> 28))
1224 ret = obj_reloc_overflow;
1225 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1226 break;
1227
1228 case R_NIOS2_IMM5:
1229 {
1230 Elf32_Addr word;
1231
1232 if (v > 0x1f) {
1233 ret = obj_reloc_overflow;
1234 }
1235
1236 word = *loc & ~0x7c0;
1237 *loc = word | ((v & 0x1f) << 6);
1238 }
1239 break;
1240
1241 case R_NIOS2_IMM6:
1242 {
1243 Elf32_Addr word;
1244
1245 if (v > 0x3f) {
1246 ret = obj_reloc_overflow;
1247 }
1248
1249 word = *loc & ~0xfc0;
1250 *loc = word | ((v & 0x3f) << 6);
1251 }
1252 break;
1253
1254 case R_NIOS2_IMM8:
1255 {
1256 Elf32_Addr word;
1257
1258 if (v > 0xff) {
1259 ret = obj_reloc_overflow;
1260 }
1261
1262 word = *loc & ~0x3fc0;
1263 *loc = word | ((v & 0xff) << 6);
1264 }
1265 break;
1266
1267 case R_NIOS2_HI16:
1268 {
1269 Elf32_Addr word;
1270
1271 word = *loc;
1272 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1273 (word & 0x3f);
1274 }
1275 break;
1276
1277 case R_NIOS2_LO16:
1278 {
1279 Elf32_Addr word;
1280
1281 word = *loc;
1282 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1283 (word & 0x3f);
1284 }
1285 break;
1286
1287 case R_NIOS2_HIADJ16:
1288 {
1289 Elf32_Addr word1, word2;
1290
1291 word1 = *loc;
1292 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1293 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1294 (word1 & 0x3f);
1295 }
1296 break;
1297
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001298#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001299
Eric Andersen3b1a7442003-12-24 20:30:45 +00001300 case R_PPC_ADDR16_HA:
1301 *(unsigned short *)loc = (v + 0x8000) >> 16;
1302 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001303
Eric Andersen3b1a7442003-12-24 20:30:45 +00001304 case R_PPC_ADDR16_HI:
1305 *(unsigned short *)loc = v >> 16;
1306 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001307
Eric Andersen3b1a7442003-12-24 20:30:45 +00001308 case R_PPC_ADDR16_LO:
1309 *(unsigned short *)loc = v;
1310 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001311
Eric Andersen3b1a7442003-12-24 20:30:45 +00001312 case R_PPC_REL24:
1313 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001314
Eric Andersen3b1a7442003-12-24 20:30:45 +00001315 case R_PPC_REL32:
1316 *loc = v - dot;
1317 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001318
Eric Andersen3b1a7442003-12-24 20:30:45 +00001319 case R_PPC_ADDR32:
1320 *loc = v;
1321 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001322
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001323#elif defined(__s390__)
1324
1325 case R_390_32:
1326 *(unsigned int *) loc += v;
1327 break;
1328 case R_390_16:
1329 *(unsigned short *) loc += v;
1330 break;
1331 case R_390_8:
1332 *(unsigned char *) loc += v;
1333 break;
1334
1335 case R_390_PC32:
1336 *(unsigned int *) loc += v - dot;
1337 break;
1338 case R_390_PC16DBL:
1339 *(unsigned short *) loc += (v - dot) >> 1;
1340 break;
1341 case R_390_PC16:
1342 *(unsigned short *) loc += v - dot;
1343 break;
1344
1345 case R_390_PLT32:
1346 case R_390_PLT16DBL:
1347 /* find the plt entry and initialize it. */
1348 assert(isym != NULL);
1349 pe = (struct arch_single_entry *) &isym->pltent;
1350 assert(pe->allocated);
1351 if (pe->inited == 0) {
1352 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1353 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1354 ip[1] = 0x100607f1;
1355 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1356 ip[2] = v - 2;
1357 else
1358 ip[2] = v;
1359 pe->inited = 1;
1360 }
1361
1362 /* Insert relative distance to target. */
1363 v = plt + pe->offset - dot;
1364 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1365 *(unsigned int *) loc = (unsigned int) v;
1366 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1367 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1368 break;
1369
1370 case R_390_GLOB_DAT:
1371 case R_390_JMP_SLOT:
1372 *loc = v;
1373 break;
1374
1375 case R_390_RELATIVE:
1376 *loc += f->baseaddr;
1377 break;
1378
1379 case R_390_GOTPC:
1380 assert(got != 0);
1381 *(unsigned long *) loc += got - dot;
1382 break;
1383
1384 case R_390_GOT12:
1385 case R_390_GOT16:
1386 case R_390_GOT32:
1387 assert(isym != NULL);
1388 assert(got != 0);
1389 if (!isym->gotent.inited)
1390 {
1391 isym->gotent.inited = 1;
1392 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1393 }
1394 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1395 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1396 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1397 *(unsigned short *) loc += isym->gotent.offset;
1398 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1399 *(unsigned int *) loc += isym->gotent.offset;
1400 break;
1401
1402# ifndef R_390_GOTOFF32
1403# define R_390_GOTOFF32 R_390_GOTOFF
1404# endif
1405 case R_390_GOTOFF32:
1406 assert(got != 0);
1407 *loc += v - got;
1408 break;
1409
Eric Andersencffd5022002-05-24 06:50:15 +00001410#elif defined(__sh__)
1411
Eric Andersen3b1a7442003-12-24 20:30:45 +00001412 case R_SH_NONE:
1413 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001414
Eric Andersen3b1a7442003-12-24 20:30:45 +00001415 case R_SH_DIR32:
1416 *loc += v;
1417 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001418
Eric Andersen3b1a7442003-12-24 20:30:45 +00001419 case R_SH_REL32:
1420 *loc += v - dot;
1421 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001422
Eric Andersen3b1a7442003-12-24 20:30:45 +00001423 case R_SH_PLT32:
1424 *loc = v - dot;
1425 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001426
Eric Andersen3b1a7442003-12-24 20:30:45 +00001427 case R_SH_GLOB_DAT:
1428 case R_SH_JMP_SLOT:
1429 *loc = v;
1430 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001431
Eric Andersen3b1a7442003-12-24 20:30:45 +00001432 case R_SH_RELATIVE:
1433 *loc = f->baseaddr + rel->r_addend;
1434 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001435
Eric Andersen3b1a7442003-12-24 20:30:45 +00001436 case R_SH_GOTPC:
1437 assert(got != 0);
1438 *loc = got - dot + rel->r_addend;
1439 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001440
Eric Andersen3b1a7442003-12-24 20:30:45 +00001441 case R_SH_GOT32:
1442 goto bb_use_got;
1443
1444 case R_SH_GOTOFF:
1445 assert(got != 0);
1446 *loc = v - got;
1447 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001448
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001449# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001450 case R_SH_IMM_MEDLOW16:
1451 case R_SH_IMM_LOW16:
1452 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001453 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001454
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001455 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001456 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001457
Eric Andersen3b1a7442003-12-24 20:30:45 +00001458 /*
1459 * movi and shori have the format:
1460 *
1461 * | op | imm | reg | reserved |
1462 * 31..26 25..10 9.. 4 3 .. 0
1463 *
1464 * so we simply mask and or in imm.
1465 */
1466 word = *loc & ~0x3fffc00;
1467 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001468
Eric Andersen3b1a7442003-12-24 20:30:45 +00001469 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001470
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 break;
1472 }
Eric Andersenbf833552003-08-13 19:56:33 +00001473
Eric Andersen3b1a7442003-12-24 20:30:45 +00001474 case R_SH_IMM_MEDLOW16_PCREL:
1475 case R_SH_IMM_LOW16_PCREL:
1476 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001477 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001480
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001482
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001483 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001485
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001487
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 break;
1491 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001492# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001493
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001494#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001495
Eric Andersen3b1a7442003-12-24 20:30:45 +00001496 case R_V850_NONE:
1497 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001498
Eric Andersen3b1a7442003-12-24 20:30:45 +00001499 case R_V850_32:
1500 /* We write two shorts instead of a long because even
1501 32-bit insns only need half-word alignment, but
1502 32-bit data needs to be long-word aligned. */
1503 v += ((unsigned short *)loc)[0];
1504 v += ((unsigned short *)loc)[1] << 16;
1505 ((unsigned short *)loc)[0] = v & 0xffff;
1506 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1507 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001508
Eric Andersen3b1a7442003-12-24 20:30:45 +00001509 case R_V850_22_PCREL:
1510 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001511
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001512#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001513
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001514 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001515 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001516
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001517 case R_X86_64_64:
1518 *loc += v;
1519 break;
1520
1521 case R_X86_64_32:
1522 *(unsigned int *) loc += v;
1523 if (v > 0xffffffff)
1524 {
1525 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1526 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1527 }
1528 break;
1529
1530 case R_X86_64_32S:
1531 *(signed int *) loc += v;
1532 break;
1533
1534 case R_X86_64_16:
1535 *(unsigned short *) loc += v;
1536 break;
1537
1538 case R_X86_64_8:
1539 *(unsigned char *) loc += v;
1540 break;
1541
1542 case R_X86_64_PC32:
1543 *(unsigned int *) loc += v - dot;
1544 break;
1545
1546 case R_X86_64_PC16:
1547 *(unsigned short *) loc += v - dot;
1548 break;
1549
1550 case R_X86_64_PC8:
1551 *(unsigned char *) loc += v - dot;
1552 break;
1553
1554 case R_X86_64_GLOB_DAT:
1555 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001556 *loc = v;
1557 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001558
1559 case R_X86_64_RELATIVE:
1560 *loc += f->baseaddr;
1561 break;
1562
1563 case R_X86_64_GOT32:
1564 case R_X86_64_GOTPCREL:
1565 goto bb_use_got;
1566# if 0
1567 assert(isym != NULL);
1568 if (!isym->gotent.reloc_done)
1569 {
1570 isym->gotent.reloc_done = 1;
1571 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1572 }
1573 /* XXX are these really correct? */
1574 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1575 *(unsigned int *) loc += v + isym->gotent.offset;
1576 else
1577 *loc += isym->gotent.offset;
1578 break;
1579# endif
1580
Mike Frysingerf982d862006-01-04 00:11:26 +00001581#else
1582# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001583#endif
1584
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001585 default:
1586 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1587 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001588 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001589
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001590#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001591
Eric Andersen3b1a7442003-12-24 20:30:45 +00001592bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001593
Eric Andersen3b1a7442003-12-24 20:30:45 +00001594 /* find the plt entry and initialize it if necessary */
1595 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001596
Eric Andersencffd5022002-05-24 06:50:15 +00001597#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001598 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1599 pe = pe->next;
1600 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001601#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001602 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001603#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001604
Eric Andersen3b1a7442003-12-24 20:30:45 +00001605 if (! pe->inited) {
1606 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001607
Eric Andersen3b1a7442003-12-24 20:30:45 +00001608 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001609
1610#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001611 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1612 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001613#endif
1614#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001615 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001616 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001617 ip[2] = 0x7d6903a6; /* mtctr r11 */
1618 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001619#endif
Miles Baderae28b042002-04-01 09:34:25 +00001620#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001621 /* We have to trash a register, so we assume that any control
1622 transfer more than 21-bits away must be a function call
1623 (so we can use a call-clobbered register). */
1624 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1625 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001626#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001627 pe->inited = 1;
1628 }
Eric Andersen21adca72000-12-06 18:18:26 +00001629
Eric Andersen3b1a7442003-12-24 20:30:45 +00001630 /* relative distance to target */
1631 v -= dot;
1632 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001633#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001634 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001635#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001636 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001637#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001638 /* go via the plt */
1639 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001640
1641#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001643#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001645#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001647
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001649#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 /* Convert to words. */
1651 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001652
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001654#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001655#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001656 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657#endif
Miles Baderae28b042002-04-01 09:34:25 +00001658#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 /* We write two shorts instead of a long because even 32-bit insns
1660 only need half-word alignment, but the 32-bit data write needs
1661 to be long-word aligned. */
1662 ((unsigned short *)loc)[0] =
1663 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1664 | ((v >> 16) & 0x3f); /* offs high part */
1665 ((unsigned short *)loc)[1] =
1666 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001667#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001668 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001669#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001670
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001671#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001672bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001673
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674 assert(isym != NULL);
1675 /* needs an entry in the .got: set it, once */
1676 if (!isym->gotent.inited) {
1677 isym->gotent.inited = 1;
1678 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1679 }
1680 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001681#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001683#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001685#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001687
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001688#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001689 }
1690
1691 return ret;
1692}
1693
Eric Andersencffd5022002-05-24 06:50:15 +00001694
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001695#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001696
1697static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1698 int offset, int size)
1699{
1700 struct arch_list_entry *pe;
1701
1702 for (pe = *list; pe != NULL; pe = pe->next) {
1703 if (pe->addend == rel->r_addend) {
1704 break;
1705 }
1706 }
1707
1708 if (pe == NULL) {
1709 pe = xmalloc(sizeof(struct arch_list_entry));
1710 pe->next = *list;
1711 pe->addend = rel->r_addend;
1712 pe->offset = offset;
1713 pe->inited = 0;
1714 *list = pe;
1715 return size;
1716 }
1717 return 0;
1718}
1719
1720#endif
1721
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001722#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001723
1724static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1725 int offset, int size)
1726{
1727 if (single->allocated == 0) {
1728 single->allocated = 1;
1729 single->offset = offset;
1730 single->inited = 0;
1731 return size;
1732 }
1733 return 0;
1734}
1735
1736#endif
1737
1738#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1739
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001740static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001741 int offset, int size)
1742{
1743 struct obj_section *myrelsec = obj_find_section(f, name);
1744
1745 if (offset == 0) {
1746 offset += size;
1747 }
1748
1749 if (myrelsec) {
1750 obj_extend_section(myrelsec, offset);
1751 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001752 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001753 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001754 assert(myrelsec);
1755 }
1756
1757 return myrelsec;
1758}
1759
1760#endif
1761
1762static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001763{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001764#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001765 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001766 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001767#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001768 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001769#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001770#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001771 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001772#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001773 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001774 ElfW(RelM) *rel, *relend;
1775 ElfW(Sym) *symtab, *extsym;
1776 const char *strtab, *name;
1777 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001778
Eric Andersen21adca72000-12-06 18:18:26 +00001779 for (i = 0; i < f->header.e_shnum; ++i) {
1780 relsec = f->sections[i];
1781 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001782 continue;
1783
Eric Andersen21adca72000-12-06 18:18:26 +00001784 symsec = f->sections[relsec->header.sh_link];
1785 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001786
Eric Andersen21adca72000-12-06 18:18:26 +00001787 rel = (ElfW(RelM) *) relsec->contents;
1788 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1789 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001790 strtab = (const char *) strsec->contents;
1791
1792 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001793 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001794
Eric Andersencffd5022002-05-24 06:50:15 +00001795#if defined(CONFIG_USE_GOT_ENTRIES)
1796 got_allocate = 0;
1797#endif
1798#if defined(CONFIG_USE_PLT_ENTRIES)
1799 plt_allocate = 0;
1800#endif
1801
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001802 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001803#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001804 case R_ARM_PC24:
1805 case R_ARM_PLT32:
1806 plt_allocate = 1;
1807 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001808
Eric Andersen3b1a7442003-12-24 20:30:45 +00001809 case R_ARM_GOTOFF:
1810 case R_ARM_GOTPC:
1811 got_needed = 1;
1812 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001813
Eric Andersen3b1a7442003-12-24 20:30:45 +00001814 case R_ARM_GOT32:
1815 got_allocate = 1;
1816 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001817
Eric Andersen21adca72000-12-06 18:18:26 +00001818#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001819 case R_386_GOTPC:
1820 case R_386_GOTOFF:
1821 got_needed = 1;
1822 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001823
Eric Andersen3b1a7442003-12-24 20:30:45 +00001824 case R_386_GOT32:
1825 got_allocate = 1;
1826 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001827
1828#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001829 case R_PPC_REL24:
1830 plt_allocate = 1;
1831 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001832
1833#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001834 case R_68K_GOT32:
1835 got_allocate = 1;
1836 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001837
Eric Andersen16451a02004-03-19 12:16:18 +00001838#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001839 case R_68K_GOTOFF:
1840 got_needed = 1;
1841 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001842#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001843
1844#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001845 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001846 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001847 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001848
Eric Andersen3b1a7442003-12-24 20:30:45 +00001849 case R_SH_GOTPC:
1850 case R_SH_GOTOFF:
1851 got_needed = 1;
1852 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001853
1854#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001855 case R_V850_22_PCREL:
1856 plt_needed = 1;
1857 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001858
1859#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001860 default:
1861 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001862 }
1863
Eric Andersen21adca72000-12-06 18:18:26 +00001864 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001865 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001866 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001867 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001868 }
1869 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001870#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001871 if (got_allocate) {
1872 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001873 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001874 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001875
1876 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001877 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001878#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001879#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001880 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001881#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001882 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001883 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001884 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001885#else
1886 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001887 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001888 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001889#endif
1890 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001891 }
1892#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001893 }
Miles Baderae28b042002-04-01 09:34:25 +00001894 }
Eric Andersen21adca72000-12-06 18:18:26 +00001895
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001896#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001897 if (got_needed) {
1898 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001899 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001900 }
Eric Andersen21adca72000-12-06 18:18:26 +00001901#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001902
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001903#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001904 if (plt_needed) {
1905 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001906 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001907 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001908#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001909
1910#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001911}
1912
Eric Andersen9f16d612000-06-12 23:11:16 +00001913/*======================================================================*/
1914
1915/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001916static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001917{
1918 unsigned long h = 0;
1919 unsigned long g;
1920 unsigned char ch;
1921
1922 while (n > 0) {
1923 ch = *name++;
1924 h = (h << 4) + ch;
1925 if ((g = (h & 0xf0000000)) != 0) {
1926 h ^= g >> 24;
1927 h &= ~g;
1928 }
1929 n--;
1930 }
1931 return h;
1932}
1933
Eric Andersen044228d2001-07-17 01:12:36 +00001934static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001935{
1936 return obj_elf_hash_n(name, strlen(name));
1937}
1938
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001939#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001940/* String comparison for non-co-versioned kernel and module. */
1941
1942static int ncv_strcmp(const char *a, const char *b)
1943{
1944 size_t alen = strlen(a), blen = strlen(b);
1945
1946 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1947 return strncmp(a, b, alen);
1948 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1949 return strncmp(a, b, blen);
1950 else
1951 return strcmp(a, b);
1952}
1953
1954/* String hashing for non-co-versioned kernel and module. Here
1955 we are simply forced to drop the crc from the hash. */
1956
1957static unsigned long ncv_symbol_hash(const char *str)
1958{
1959 size_t len = strlen(str);
1960 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1961 len -= 10;
1962 return obj_elf_hash_n(str, len);
1963}
1964
Eric Andersen044228d2001-07-17 01:12:36 +00001965static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001966obj_set_symbol_compare(struct obj_file *f,
1967 int (*cmp) (const char *, const char *),
1968 unsigned long (*hash) (const char *))
1969{
1970 if (cmp)
1971 f->symbol_cmp = cmp;
1972 if (hash) {
1973 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1974 int i;
1975
1976 f->symbol_hash = hash;
1977
1978 memcpy(tmptab, f->symtab, sizeof(tmptab));
1979 memset(f->symtab, 0, sizeof(f->symtab));
1980
1981 for (i = 0; i < HASH_BUCKETS; ++i)
1982 for (sym = tmptab[i]; sym; sym = next) {
1983 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1984 next = sym->next;
1985 sym->next = f->symtab[h];
1986 f->symtab[h] = sym;
1987 }
1988 }
1989}
1990
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001991#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001992
Eric Andersen044228d2001-07-17 01:12:36 +00001993static struct obj_symbol *
1994obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001995 unsigned long symidx, int info,
1996 int secidx, ElfW(Addr) value,
1997 unsigned long size)
1998{
1999 struct obj_symbol *sym;
2000 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002001 int n_type = ELF_ST_TYPE(info);
2002 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002003
2004 for (sym = f->symtab[hash]; sym; sym = sym->next)
2005 if (f->symbol_cmp(sym->name, name) == 0) {
2006 int o_secidx = sym->secidx;
2007 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002008 int o_type = ELF_ST_TYPE(o_info);
2009 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002010
2011 /* A redefinition! Is it legal? */
2012
2013 if (secidx == SHN_UNDEF)
2014 return sym;
2015 else if (o_secidx == SHN_UNDEF)
2016 goto found;
2017 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2018 /* Cope with local and global symbols of the same name
2019 in the same object file, as might have been created
2020 by ld -r. The only reason locals are now seen at this
2021 level at all is so that we can do semi-sensible things
2022 with parameters. */
2023
2024 struct obj_symbol *nsym, **p;
2025
2026 nsym = arch_new_symbol();
2027 nsym->next = sym->next;
2028 nsym->ksymidx = -1;
2029
2030 /* Excise the old (local) symbol from the hash chain. */
2031 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2032 continue;
2033 *p = sym = nsym;
2034 goto found;
2035 } else if (n_binding == STB_LOCAL) {
2036 /* Another symbol of the same name has already been defined.
2037 Just add this to the local table. */
2038 sym = arch_new_symbol();
2039 sym->next = NULL;
2040 sym->ksymidx = -1;
2041 f->local_symtab[symidx] = sym;
2042 goto found;
2043 } else if (n_binding == STB_WEAK)
2044 return sym;
2045 else if (o_binding == STB_WEAK)
2046 goto found;
2047 /* Don't unify COMMON symbols with object types the programmer
2048 doesn't expect. */
2049 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002050 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002051 return sym;
2052 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002053 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002054 goto found;
2055 else {
2056 /* Don't report an error if the symbol is coming from
2057 the kernel or some external module. */
2058 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002059 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002060 return sym;
2061 }
2062 }
2063
2064 /* Completely new symbol. */
2065 sym = arch_new_symbol();
2066 sym->next = f->symtab[hash];
2067 f->symtab[hash] = sym;
2068 sym->ksymidx = -1;
2069
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002070 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002071 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002072 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002073 name, (long) symidx, (long) f->local_symtab_size);
2074 else
2075 f->local_symtab[symidx] = sym;
2076 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002077
Eric Andersen3b1a7442003-12-24 20:30:45 +00002078found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002079 sym->name = name;
2080 sym->value = value;
2081 sym->size = size;
2082 sym->secidx = secidx;
2083 sym->info = info;
2084
2085 return sym;
2086}
2087
Eric Andersen044228d2001-07-17 01:12:36 +00002088static struct obj_symbol *
2089obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002090{
2091 struct obj_symbol *sym;
2092 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2093
2094 for (sym = f->symtab[hash]; sym; sym = sym->next)
2095 if (f->symbol_cmp(sym->name, name) == 0)
2096 return sym;
2097
2098 return NULL;
2099}
2100
Eric Andersen044228d2001-07-17 01:12:36 +00002101static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002102 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2103{
2104 if (sym) {
2105 if (sym->secidx >= SHN_LORESERVE)
2106 return sym->value;
2107
2108 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2109 } else {
2110 /* As a special case, a NULL sym has value zero. */
2111 return 0;
2112 }
2113}
2114
Eric Andersen044228d2001-07-17 01:12:36 +00002115static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002116{
2117 int i, n = f->header.e_shnum;
2118
2119 for (i = 0; i < n; ++i)
2120 if (strcmp(f->sections[i]->name, name) == 0)
2121 return f->sections[i];
2122
2123 return NULL;
2124}
2125
2126static int obj_load_order_prio(struct obj_section *a)
2127{
2128 unsigned long af, ac;
2129
2130 af = a->header.sh_flags;
2131
2132 ac = 0;
2133 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002134 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002135 ac |= 32;
2136 if (af & SHF_ALLOC)
2137 ac |= 16;
2138 if (!(af & SHF_WRITE))
2139 ac |= 8;
2140 if (af & SHF_EXECINSTR)
2141 ac |= 4;
2142 if (a->header.sh_type != SHT_NOBITS)
2143 ac |= 2;
2144
2145 return ac;
2146}
2147
Eric Andersen044228d2001-07-17 01:12:36 +00002148static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002149obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2150{
2151 struct obj_section **p;
2152 int prio = obj_load_order_prio(sec);
2153 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2154 if (obj_load_order_prio(*p) < prio)
2155 break;
2156 sec->load_next = *p;
2157 *p = sec;
2158}
2159
Eric Andersen044228d2001-07-17 01:12:36 +00002160static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002161 const char *name,
2162 unsigned long align,
2163 unsigned long size)
2164{
2165 int newidx = f->header.e_shnum++;
2166 struct obj_section *sec;
2167
2168 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2169 f->sections[newidx] = sec = arch_new_section();
2170
2171 memset(sec, 0, sizeof(*sec));
2172 sec->header.sh_type = SHT_PROGBITS;
2173 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2174 sec->header.sh_size = size;
2175 sec->header.sh_addralign = align;
2176 sec->name = name;
2177 sec->idx = newidx;
2178 if (size)
2179 sec->contents = xmalloc(size);
2180
2181 obj_insert_section_load_order(f, sec);
2182
2183 return sec;
2184}
2185
Eric Andersen044228d2001-07-17 01:12:36 +00002186static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002187 const char *name,
2188 unsigned long align,
2189 unsigned long size)
2190{
2191 int newidx = f->header.e_shnum++;
2192 struct obj_section *sec;
2193
2194 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2195 f->sections[newidx] = sec = arch_new_section();
2196
2197 memset(sec, 0, sizeof(*sec));
2198 sec->header.sh_type = SHT_PROGBITS;
2199 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2200 sec->header.sh_size = size;
2201 sec->header.sh_addralign = align;
2202 sec->name = name;
2203 sec->idx = newidx;
2204 if (size)
2205 sec->contents = xmalloc(size);
2206
2207 sec->load_next = f->load_order;
2208 f->load_order = sec;
2209 if (f->load_order_search_start == &f->load_order)
2210 f->load_order_search_start = &sec->load_next;
2211
2212 return sec;
2213}
2214
Eric Andersen044228d2001-07-17 01:12:36 +00002215static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002216{
2217 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002218 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002219 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2220 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002221 return sec->contents + oldsize;
2222}
2223
2224
Eric Andersen9f16d612000-06-12 23:11:16 +00002225/* Conditionally add the symbols from the given symbol set to the
2226 new module. */
2227
2228static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002229add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002230 int idx, struct new_module_symbol *syms, size_t nsyms)
2231{
2232 struct new_module_symbol *s;
2233 size_t i;
2234 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002235#ifdef SYMBOL_PREFIX
2236 char *name_buf = 0;
2237 size_t name_alloced_size = 0;
2238#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002239#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2240 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002241
Glenn L McGrath759515c2003-08-30 06:00:33 +00002242 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002243#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002244 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002245 /* Only add symbols that are already marked external.
2246 If we override locals we may cause problems for
2247 argument initialization. We will also create a false
2248 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002249 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002250 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002251
Glenn L McGrath759515c2003-08-30 06:00:33 +00002252 /* GPL licensed modules can use symbols exported with
2253 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2254 * exported names. Non-GPL modules never see any GPLONLY_
2255 * symbols so they cannot fudge it by adding the prefix on
2256 * their references.
2257 */
2258 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002259#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002260 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002261 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002262 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002263#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002264 continue;
2265 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002266 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002267
Miles Baderae28b042002-04-01 09:34:25 +00002268#ifdef SYMBOL_PREFIX
2269 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2270 kernel exports `C names', but module object files
2271 reference `linker names'). */
2272 size_t extra = sizeof SYMBOL_PREFIX;
2273 size_t name_size = strlen (name) + extra;
2274 if (name_size > name_alloced_size) {
2275 name_alloced_size = name_size * 2;
2276 name_buf = alloca (name_alloced_size);
2277 }
2278 strcpy (name_buf, SYMBOL_PREFIX);
2279 strcpy (name_buf + extra - 1, name);
2280 name = name_buf;
2281#endif /* SYMBOL_PREFIX */
2282
2283 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002284 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002285#ifdef SYMBOL_PREFIX
2286 /* Put NAME_BUF into more permanent storage. */
2287 name = xmalloc (name_size);
2288 strcpy (name, name_buf);
2289#endif
2290 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002291 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002292 STT_NOTYPE),
2293 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002294 /* Did our symbol just get installed? If so, mark the
2295 module as "used". */
2296 if (sym->secidx == idx)
2297 used = 1;
2298 }
2299 }
2300
2301 return used;
2302}
2303
2304static void add_kernel_symbols(struct obj_file *f)
2305{
2306 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002307 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002308
2309 /* Add module symbols first. */
2310
2311 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2312 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002313 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2314 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002315
2316 n_ext_modules_used = nused;
2317
2318 /* And finally the symbols from the kernel proper. */
2319
2320 if (nksyms)
2321 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2322}
2323
2324static char *get_modinfo_value(struct obj_file *f, const char *key)
2325{
2326 struct obj_section *sec;
2327 char *p, *v, *n, *ep;
2328 size_t klen = strlen(key);
2329
2330 sec = obj_find_section(f, ".modinfo");
2331 if (sec == NULL)
2332 return NULL;
2333 p = sec->contents;
2334 ep = p + sec->header.sh_size;
2335 while (p < ep) {
2336 v = strchr(p, '=');
2337 n = strchr(p, '\0');
2338 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002339 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002340 return v + 1;
2341 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002342 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002343 return n;
2344 }
2345 p = n + 1;
2346 }
2347
2348 return NULL;
2349}
2350
2351
2352/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002353/* Functions relating to module loading after 2.1.18. */
2354
2355static int
2356new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2357{
2358 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002359 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002360 struct obj_symbol *sym;
2361 char *contents, *loc;
2362 int min, max, n;
2363
2364 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002365 if ((q = strchr(p, '=')) == NULL) {
2366 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002367 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002368 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002369
2370 key = alloca(q - p + 6);
2371 memcpy(key, "parm_", 5);
2372 memcpy(key + 5, p, q - p);
2373 key[q - p + 5] = 0;
2374
2375 p = get_modinfo_value(f, key);
2376 key += 5;
2377 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002378 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002379 return 0;
2380 }
2381
Miles Baderae28b042002-04-01 09:34:25 +00002382#ifdef SYMBOL_PREFIX
2383 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2384 strcpy (sym_name, SYMBOL_PREFIX);
2385 strcat (sym_name, key);
2386#else
2387 sym_name = key;
2388#endif
2389 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002390
2391 /* Also check that the parameter was not resolved from the kernel. */
2392 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002393 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002394 return 0;
2395 }
2396
2397 if (isdigit(*p)) {
2398 min = strtoul(p, &p, 10);
2399 if (*p == '-')
2400 max = strtoul(p + 1, &p, 10);
2401 else
2402 max = min;
2403 } else
2404 min = max = 1;
2405
2406 contents = f->sections[sym->secidx]->contents;
2407 loc = contents + sym->value;
2408 n = (*++q != '\0');
2409
2410 while (1) {
2411 if ((*p == 's') || (*p == 'c')) {
2412 char *str;
2413
2414 /* Do C quoting if we begin with a ", else slurp the lot. */
2415 if (*q == '"') {
2416 char *r;
2417
2418 str = alloca(strlen(q));
2419 for (r = str, q++; *q != '"'; ++q, ++r) {
2420 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002421 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002422 key);
2423 return 0;
2424 } else if (*q == '\\')
2425 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002426 case 'a':
2427 *r = '\a';
2428 break;
2429 case 'b':
2430 *r = '\b';
2431 break;
2432 case 'e':
2433 *r = '\033';
2434 break;
2435 case 'f':
2436 *r = '\f';
2437 break;
2438 case 'n':
2439 *r = '\n';
2440 break;
2441 case 'r':
2442 *r = '\r';
2443 break;
2444 case 't':
2445 *r = '\t';
2446 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002447
Eric Andersen3b1a7442003-12-24 20:30:45 +00002448 case '0':
2449 case '1':
2450 case '2':
2451 case '3':
2452 case '4':
2453 case '5':
2454 case '6':
2455 case '7':
2456 {
2457 int c = *q - '0';
2458 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002459 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002460 if (q[1] >= '0' && q[1] <= '7')
2461 c = (c * 8) + *++q - '0';
2462 }
2463 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002464 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002465 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002466
Eric Andersen3b1a7442003-12-24 20:30:45 +00002467 default:
2468 *r = *q;
2469 break;
2470 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002471 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002472 }
2473 *r = '\0';
2474 ++q;
2475 } else {
2476 char *r;
2477
2478 /* In this case, the string is not quoted. We will break
2479 it using the coma (like for ints). If the user wants to
2480 include comas in a string, he just has to quote it */
2481
2482 /* Search the next coma */
2483 r = strchr(q, ',');
2484
2485 /* Found ? */
2486 if (r != (char *) NULL) {
2487 /* Recopy the current field */
2488 str = alloca(r - q + 1);
2489 memcpy(str, q, r - q);
2490
Eric Andersenaff114c2004-04-14 17:51:38 +00002491 /* I don't know if it is useful, as the previous case
2492 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002493 str[r - q] = '\0';
2494
2495 /* Keep next fields */
2496 q = r;
2497 } else {
2498 /* last string */
2499 str = q;
2500 q = "";
2501 }
2502 }
2503
2504 if (*p == 's') {
2505 /* Normal string */
2506 obj_string_patch(f, sym->secidx, loc - contents, str);
2507 loc += tgt_sizeof_char_p;
2508 } else {
2509 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002510 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002511
2512 /* Get the size of each member */
2513 /* Probably we should do that outside the loop ? */
2514 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002515 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002516 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002517 return 0;
2518 }
2519 charssize = strtoul(p + 1, (char **) NULL, 10);
2520
2521 /* Check length */
2522 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002523 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002524 charssize - 1);
2525 return 0;
2526 }
2527
2528 /* Copy to location */
2529 strcpy((char *) loc, str);
2530 loc += charssize;
2531 }
2532 } else {
2533 long v = strtoul(q, &q, 0);
2534 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002535 case 'b':
2536 *loc++ = v;
2537 break;
2538 case 'h':
2539 *(short *) loc = v;
2540 loc += tgt_sizeof_short;
2541 break;
2542 case 'i':
2543 *(int *) loc = v;
2544 loc += tgt_sizeof_int;
2545 break;
2546 case 'l':
2547 *(long *) loc = v;
2548 loc += tgt_sizeof_long;
2549 break;
2550
2551 default:
2552 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2553 return 0;
2554 }
2555 }
2556
2557retry_end_of_value:
2558 switch (*q) {
2559 case '\0':
2560 goto end_of_arg;
2561
2562 case ' ':
2563 case '\t':
2564 case '\n':
2565 case '\r':
2566 ++q;
2567 goto retry_end_of_value;
2568
2569 case ',':
2570 if (++n > max) {
2571 bb_error_msg("too many values for %s (max %d)", key, max);
2572 return 0;
2573 }
2574 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002575 break;
2576
2577 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002578 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002579 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002580 }
2581 }
2582
Eric Andersen3b1a7442003-12-24 20:30:45 +00002583end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002584 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002585 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002586 return 0;
2587 }
2588
2589 argc--, argv++;
2590 }
2591
2592 return 1;
2593}
2594
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002595#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002596static int new_is_module_checksummed(struct obj_file *f)
2597{
2598 const char *p = get_modinfo_value(f, "using_checksums");
2599 if (p)
2600 return atoi(p);
2601 else
2602 return 0;
2603}
2604
2605/* Get the module's kernel version in the canonical integer form. */
2606
2607static int
2608new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2609{
2610 char *p, *q;
2611 int a, b, c;
2612
2613 p = get_modinfo_value(f, "kernel_version");
2614 if (p == NULL)
2615 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002616 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002617
2618 a = strtoul(p, &p, 10);
2619 if (*p != '.')
2620 return -1;
2621 b = strtoul(p + 1, &p, 10);
2622 if (*p != '.')
2623 return -1;
2624 c = strtoul(p + 1, &q, 10);
2625 if (p + 1 == q)
2626 return -1;
2627
2628 return a << 16 | b << 8 | c;
2629}
2630
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002631#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002632
2633
Eric Andersen9f16d612000-06-12 23:11:16 +00002634/* Fetch the loaded modules, and all currently exported symbols. */
2635
2636static int new_get_kernel_symbols(void)
2637{
2638 char *module_names, *mn;
2639 struct external_module *modules, *m;
2640 struct new_module_symbol *syms, *s;
2641 size_t ret, bufsize, nmod, nsyms, i, j;
2642
2643 /* Collect the loaded modules. */
2644
2645 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002646retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002647 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002648 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002649 module_names = xrealloc(module_names, bufsize = ret);
2650 goto retry_modules_load;
2651 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002652 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002653 return 0;
2654 }
2655
2656 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002657
2658 /* Collect the modules' symbols. */
2659
Mark Whitley94fd4802001-03-12 23:08:34 +00002660 if (nmod){
2661 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2662 memset(modules, 0, nmod * sizeof(*modules));
2663 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002664 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002665 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002666
Mark Whitley94fd4802001-03-12 23:08:34 +00002667 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2668 if (errno == ENOENT) {
2669 /* The module was removed out from underneath us. */
2670 continue;
2671 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002672 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002673 return 0;
2674 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002675
Mark Whitley94fd4802001-03-12 23:08:34 +00002676 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002677retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002678 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2679 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002680 case ENOSPC:
2681 syms = xrealloc(syms, bufsize = ret);
2682 goto retry_mod_sym_load;
2683 case ENOENT:
2684 /* The module was removed out from underneath us. */
2685 continue;
2686 default:
2687 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2688 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002689 }
2690 }
2691 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002692
Mark Whitley94fd4802001-03-12 23:08:34 +00002693 m->name = mn;
2694 m->addr = info.addr;
2695 m->nsyms = nsyms;
2696 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002697
Mark Whitley94fd4802001-03-12 23:08:34 +00002698 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2699 s->name += (unsigned long) syms;
2700 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002701 }
2702 }
2703
2704 /* Collect the kernel's symbols. */
2705
2706 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002707retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002708 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002709 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002710 syms = xrealloc(syms, bufsize = ret);
2711 goto retry_kern_sym_load;
2712 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002713 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002714 return 0;
2715 }
2716 nksyms = nsyms = ret;
2717 ksyms = syms;
2718
2719 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2720 s->name += (unsigned long) syms;
2721 }
2722 return 1;
2723}
2724
2725
2726/* Return the kernel symbol checksum version, or zero if not used. */
2727
2728static int new_is_kernel_checksummed(void)
2729{
2730 struct new_module_symbol *s;
2731 size_t i;
2732
2733 /* Using_Versions is not the first symbol, but it should be in there. */
2734
2735 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2736 if (strcmp((char *) s->name, "Using_Versions") == 0)
2737 return s->value;
2738
2739 return 0;
2740}
2741
2742
2743static int new_create_this_module(struct obj_file *f, const char *m_name)
2744{
2745 struct obj_section *sec;
2746
2747 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002748 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002749 memset(sec->contents, 0, sizeof(struct new_module));
2750
Miles Baderae28b042002-04-01 09:34:25 +00002751 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002752 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002753 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002754
2755 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002756 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002757
2758 return 1;
2759}
2760
Eric Andersen889dd202003-01-23 04:48:34 +00002761#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2762/* add an entry to the __ksymtab section, creating it if necessary */
2763static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2764{
2765 struct obj_section *sec;
2766 ElfW(Addr) ofs;
2767
2768 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2769 * If __ksymtab is defined but not marked alloc, x out the first character
2770 * (no obj_delete routine) and create a new __ksymtab with the correct
2771 * characteristics.
2772 */
2773 sec = obj_find_section(f, "__ksymtab");
2774 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2775 *((char *)(sec->name)) = 'x'; /* override const */
2776 sec = NULL;
2777 }
2778 if (!sec)
2779 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002780 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002781 if (!sec)
2782 return;
2783 sec->header.sh_flags |= SHF_ALLOC;
2784 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002785 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002786 ofs = sec->header.sh_size;
2787 obj_symbol_patch(f, sec->idx, ofs, sym);
2788 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2789 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2790}
2791#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002792
2793static int new_create_module_ksymtab(struct obj_file *f)
2794{
2795 struct obj_section *sec;
2796 int i;
2797
2798 /* We must always add the module references. */
2799
2800 if (n_ext_modules_used) {
2801 struct new_module_ref *dep;
2802 struct obj_symbol *tm;
2803
2804 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002805 (sizeof(struct new_module_ref)
2806 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002807 if (!sec)
2808 return 0;
2809
Miles Baderae28b042002-04-01 09:34:25 +00002810 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002811 dep = (struct new_module_ref *) sec->contents;
2812 for (i = 0; i < n_ext_modules; ++i)
2813 if (ext_modules[i].used) {
2814 dep->dep = ext_modules[i].addr;
2815 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002816 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002817 dep->next_ref = 0;
2818 ++dep;
2819 }
2820 }
2821
2822 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2823 size_t nsyms;
2824 int *loaded;
2825
2826 sec =
2827 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002828 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002829
2830 /* We don't want to export symbols residing in sections that
2831 aren't loaded. There are a number of these created so that
2832 we make sure certain module options don't appear twice. */
2833
2834 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2835 while (--i >= 0)
2836 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2837
2838 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2839 struct obj_symbol *sym;
2840 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002841 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002842 && sym->secidx <= SHN_HIRESERVE
2843 && (sym->secidx >= SHN_LORESERVE
2844 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002845 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2846
2847 obj_symbol_patch(f, sec->idx, ofs, sym);
2848 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002849 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002850
2851 nsyms++;
2852 }
2853 }
2854
2855 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2856 }
2857
2858 return 1;
2859}
2860
2861
2862static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002863new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002864{
2865 struct new_module *module;
2866 struct obj_section *sec;
2867 void *image;
2868 int ret;
2869 tgt_long m_addr;
2870
2871 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002872 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002873 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002874 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002875 module = (struct new_module *) sec->contents;
2876 m_addr = sec->header.sh_addr;
2877
2878 module->size_of_struct = sizeof(*module);
2879 module->size = m_size;
2880 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2881
2882 sec = obj_find_section(f, "__ksymtab");
2883 if (sec && sec->header.sh_size) {
2884 module->syms = sec->header.sh_addr;
2885 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2886 }
2887
2888 if (n_ext_modules_used) {
2889 sec = obj_find_section(f, ".kmodtab");
2890 module->deps = sec->header.sh_addr;
2891 module->ndeps = n_ext_modules_used;
2892 }
2893
2894 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002895 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002896 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002897 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002898
2899 sec = obj_find_section(f, "__ex_table");
2900 if (sec) {
2901 module->ex_table_start = sec->header.sh_addr;
2902 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2903 }
2904
2905 sec = obj_find_section(f, ".text.init");
2906 if (sec) {
2907 module->runsize = sec->header.sh_addr - m_addr;
2908 }
2909 sec = obj_find_section(f, ".data.init");
2910 if (sec) {
2911 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002912 module->runsize > sec->header.sh_addr - m_addr)
2913 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002914 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002915 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2916 if (sec && sec->header.sh_size) {
2917 module->archdata_start = (void*)sec->header.sh_addr;
2918 module->archdata_end = module->archdata_start + sec->header.sh_size;
2919 }
2920 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2921 if (sec && sec->header.sh_size) {
2922 module->kallsyms_start = (void*)sec->header.sh_addr;
2923 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2924 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002925
Eric Andersen9f16d612000-06-12 23:11:16 +00002926 /* Whew! All of the initialization is complete. Collect the final
2927 module image and give it to the kernel. */
2928
2929 image = xmalloc(m_size);
2930 obj_create_image(f, image);
2931
Eric Andersencb3b9b12004-06-22 11:50:52 +00002932 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002933 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002934 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002935
2936 free(image);
2937
2938 return ret == 0;
2939}
2940
Eric Andersen9f16d612000-06-12 23:11:16 +00002941
2942/*======================================================================*/
2943
Eric Andersen044228d2001-07-17 01:12:36 +00002944static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002945obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2946 const char *string)
2947{
2948 struct obj_string_patch *p;
2949 struct obj_section *strsec;
2950 size_t len = strlen(string) + 1;
2951 char *loc;
2952
2953 p = xmalloc(sizeof(*p));
2954 p->next = f->string_patches;
2955 p->reloc_secidx = secidx;
2956 p->reloc_offset = offset;
2957 f->string_patches = p;
2958
2959 strsec = obj_find_section(f, ".kstrtab");
2960 if (strsec == NULL) {
2961 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2962 p->string_offset = 0;
2963 loc = strsec->contents;
2964 } else {
2965 p->string_offset = strsec->header.sh_size;
2966 loc = obj_extend_section(strsec, len);
2967 }
2968 memcpy(loc, string, len);
2969
2970 return 1;
2971}
2972
Eric Andersen044228d2001-07-17 01:12:36 +00002973static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002974obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2975 struct obj_symbol *sym)
2976{
2977 struct obj_symbol_patch *p;
2978
2979 p = xmalloc(sizeof(*p));
2980 p->next = f->symbol_patches;
2981 p->reloc_secidx = secidx;
2982 p->reloc_offset = offset;
2983 p->sym = sym;
2984 f->symbol_patches = p;
2985
2986 return 1;
2987}
2988
Eric Andersen044228d2001-07-17 01:12:36 +00002989static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002990{
2991 unsigned long i;
2992 int ret = 1;
2993
2994 for (i = 0; i < HASH_BUCKETS; ++i) {
2995 struct obj_symbol *sym;
2996 for (sym = f->symtab[i]; sym; sym = sym->next)
2997 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002998 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002999 sym->secidx = SHN_ABS;
3000 sym->value = 0;
3001 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003002 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003003 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003004 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003005 ret = 0;
3006 }
3007 }
3008 }
3009
3010 return ret;
3011}
3012
Eric Andersen044228d2001-07-17 01:12:36 +00003013static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003014{
3015 struct common_entry {
3016 struct common_entry *next;
3017 struct obj_symbol *sym;
3018 } *common_head = NULL;
3019
3020 unsigned long i;
3021
3022 for (i = 0; i < HASH_BUCKETS; ++i) {
3023 struct obj_symbol *sym;
3024 for (sym = f->symtab[i]; sym; sym = sym->next)
3025 if (sym->secidx == SHN_COMMON) {
3026 /* Collect all COMMON symbols and sort them by size so as to
3027 minimize space wasted by alignment requirements. */
3028 {
3029 struct common_entry **p, *n;
3030 for (p = &common_head; *p; p = &(*p)->next)
3031 if (sym->size <= (*p)->sym->size)
3032 break;
3033
3034 n = alloca(sizeof(*n));
3035 n->next = *p;
3036 n->sym = sym;
3037 *p = n;
3038 }
3039 }
3040 }
3041
3042 for (i = 1; i < f->local_symtab_size; ++i) {
3043 struct obj_symbol *sym = f->local_symtab[i];
3044 if (sym && sym->secidx == SHN_COMMON) {
3045 struct common_entry **p, *n;
3046 for (p = &common_head; *p; p = &(*p)->next)
3047 if (sym == (*p)->sym)
3048 break;
3049 else if (sym->size < (*p)->sym->size) {
3050 n = alloca(sizeof(*n));
3051 n->next = *p;
3052 n->sym = sym;
3053 *p = n;
3054 break;
3055 }
3056 }
3057 }
3058
3059 if (common_head) {
3060 /* Find the bss section. */
3061 for (i = 0; i < f->header.e_shnum; ++i)
3062 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3063 break;
3064
3065 /* If for some reason there hadn't been one, create one. */
3066 if (i == f->header.e_shnum) {
3067 struct obj_section *sec;
3068
3069 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3070 f->sections[i] = sec = arch_new_section();
3071 f->header.e_shnum = i + 1;
3072
3073 memset(sec, 0, sizeof(*sec));
3074 sec->header.sh_type = SHT_PROGBITS;
3075 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3076 sec->name = ".bss";
3077 sec->idx = i;
3078 }
3079
3080 /* Allocate the COMMONS. */
3081 {
3082 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3083 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3084 struct common_entry *c;
3085
3086 for (c = common_head; c; c = c->next) {
3087 ElfW(Addr) align = c->sym->value;
3088
3089 if (align > max_align)
3090 max_align = align;
3091 if (bss_size & (align - 1))
3092 bss_size = (bss_size | (align - 1)) + 1;
3093
3094 c->sym->secidx = i;
3095 c->sym->value = bss_size;
3096
3097 bss_size += c->sym->size;
3098 }
3099
3100 f->sections[i]->header.sh_size = bss_size;
3101 f->sections[i]->header.sh_addralign = max_align;
3102 }
3103 }
3104
3105 /* For the sake of patch relocation and parameter initialization,
3106 allocate zeroed data for NOBITS sections now. Note that after
3107 this we cannot assume NOBITS are really empty. */
3108 for (i = 0; i < f->header.e_shnum; ++i) {
3109 struct obj_section *s = f->sections[i];
3110 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003111 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003112 s->contents = memset(xmalloc(s->header.sh_size),
3113 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003114 else
3115 s->contents = NULL;
3116
Eric Andersen9f16d612000-06-12 23:11:16 +00003117 s->header.sh_type = SHT_PROGBITS;
3118 }
3119 }
3120}
3121
Eric Andersen044228d2001-07-17 01:12:36 +00003122static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003123{
3124 unsigned long dot = 0;
3125 struct obj_section *sec;
3126
3127 /* Finalize the positions of the sections relative to one another. */
3128
3129 for (sec = f->load_order; sec; sec = sec->load_next) {
3130 ElfW(Addr) align;
3131
3132 align = sec->header.sh_addralign;
3133 if (align && (dot & (align - 1)))
3134 dot = (dot | (align - 1)) + 1;
3135
3136 sec->header.sh_addr = dot;
3137 dot += sec->header.sh_size;
3138 }
3139
3140 return dot;
3141}
3142
Eric Andersen044228d2001-07-17 01:12:36 +00003143static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003144{
3145 int i, n = f->header.e_shnum;
3146 int ret = 1;
3147
3148 /* Finalize the addresses of the sections. */
3149
3150 f->baseaddr = base;
3151 for (i = 0; i < n; ++i)
3152 f->sections[i]->header.sh_addr += base;
3153
3154 /* And iterate over all of the relocations. */
3155
3156 for (i = 0; i < n; ++i) {
3157 struct obj_section *relsec, *symsec, *targsec, *strsec;
3158 ElfW(RelM) * rel, *relend;
3159 ElfW(Sym) * symtab;
3160 const char *strtab;
3161
3162 relsec = f->sections[i];
3163 if (relsec->header.sh_type != SHT_RELM)
3164 continue;
3165
3166 symsec = f->sections[relsec->header.sh_link];
3167 targsec = f->sections[relsec->header.sh_info];
3168 strsec = f->sections[symsec->header.sh_link];
3169
3170 rel = (ElfW(RelM) *) relsec->contents;
3171 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3172 symtab = (ElfW(Sym) *) symsec->contents;
3173 strtab = (const char *) strsec->contents;
3174
3175 for (; rel < relend; ++rel) {
3176 ElfW(Addr) value = 0;
3177 struct obj_symbol *intsym = NULL;
3178 unsigned long symndx;
3179 ElfW(Sym) * extsym = 0;
3180 const char *errmsg;
3181
3182 /* Attempt to find a value to use for this relocation. */
3183
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003184 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003185 if (symndx) {
3186 /* Note we've already checked for undefined symbols. */
3187
3188 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003189 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003190 /* Local symbols we look up in the local table to be sure
3191 we get the one that is really intended. */
3192 intsym = f->local_symtab[symndx];
3193 } else {
3194 /* Others we look up in the hash table. */
3195 const char *name;
3196 if (extsym->st_name)
3197 name = strtab + extsym->st_name;
3198 else
3199 name = f->sections[extsym->st_shndx]->name;
3200 intsym = obj_find_symbol(f, name);
3201 }
3202
3203 value = obj_symbol_final_value(f, intsym);
3204 intsym->referenced = 1;
3205 }
3206#if SHT_RELM == SHT_RELA
3207#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3208 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3209 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003210 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003211#endif
3212 value += rel->r_addend;
3213#endif
3214
3215 /* Do it! */
3216 switch (arch_apply_relocation
3217 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003218 case obj_reloc_ok:
3219 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003220
Eric Andersen3b1a7442003-12-24 20:30:45 +00003221 case obj_reloc_overflow:
3222 errmsg = "Relocation overflow";
3223 goto bad_reloc;
3224 case obj_reloc_dangerous:
3225 errmsg = "Dangerous relocation";
3226 goto bad_reloc;
3227 case obj_reloc_unhandled:
3228 errmsg = "Unhandled relocation";
3229bad_reloc:
3230 if (extsym) {
3231 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003232 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003233 strtab + extsym->st_name);
3234 } else {
3235 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003236 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003237 }
3238 ret = 0;
3239 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003240 }
3241 }
3242 }
3243
3244 /* Finally, take care of the patches. */
3245
3246 if (f->string_patches) {
3247 struct obj_string_patch *p;
3248 struct obj_section *strsec;
3249 ElfW(Addr) strsec_base;
3250 strsec = obj_find_section(f, ".kstrtab");
3251 strsec_base = strsec->header.sh_addr;
3252
3253 for (p = f->string_patches; p; p = p->next) {
3254 struct obj_section *targsec = f->sections[p->reloc_secidx];
3255 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3256 = strsec_base + p->string_offset;
3257 }
3258 }
3259
3260 if (f->symbol_patches) {
3261 struct obj_symbol_patch *p;
3262
3263 for (p = f->symbol_patches; p; p = p->next) {
3264 struct obj_section *targsec = f->sections[p->reloc_secidx];
3265 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3266 = obj_symbol_final_value(f, p->sym);
3267 }
3268 }
3269
3270 return ret;
3271}
3272
Eric Andersen044228d2001-07-17 01:12:36 +00003273static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003274{
3275 struct obj_section *sec;
3276 ElfW(Addr) base = f->baseaddr;
3277
3278 for (sec = f->load_order; sec; sec = sec->load_next) {
3279 char *secimg;
3280
Eric Andersen2bf658d2001-02-24 20:01:53 +00003281 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003282 continue;
3283
3284 secimg = image + (sec->header.sh_addr - base);
3285
3286 /* Note that we allocated data for NOBITS sections earlier. */
3287 memcpy(secimg, sec->contents, sec->header.sh_size);
3288 }
3289
3290 return 1;
3291}
3292
3293/*======================================================================*/
3294
Eric Andersen044228d2001-07-17 01:12:36 +00003295static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003296{
3297 struct obj_file *f;
3298 ElfW(Shdr) * section_headers;
3299 int shnum, i;
3300 char *shstrtab;
3301
3302 /* Read the file header. */
3303
3304 f = arch_new_file();
3305 memset(f, 0, sizeof(*f));
3306 f->symbol_cmp = strcmp;
3307 f->symbol_hash = obj_elf_hash;
3308 f->load_order_search_start = &f->load_order;
3309
3310 fseek(fp, 0, SEEK_SET);
3311 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003312 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003313 return NULL;
3314 }
3315
3316 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003317 || f->header.e_ident[EI_MAG1] != ELFMAG1
3318 || f->header.e_ident[EI_MAG2] != ELFMAG2
3319 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003320 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003321 return NULL;
3322 }
3323 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003324 || f->header.e_ident[EI_DATA] != ELFDATAM
3325 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3326 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003327 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003328 return NULL;
3329 }
3330 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003331 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003332 return NULL;
3333 }
3334
3335 /* Read the section headers. */
3336
3337 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003338 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003339 (unsigned long) f->header.e_shentsize,
3340 (unsigned long) sizeof(ElfW(Shdr)));
3341 return NULL;
3342 }
3343
3344 shnum = f->header.e_shnum;
3345 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3346 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3347
3348 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3349 fseek(fp, f->header.e_shoff, SEEK_SET);
3350 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003351 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003352 return NULL;
3353 }
3354
3355 /* Read the section data. */
3356
3357 for (i = 0; i < shnum; ++i) {
3358 struct obj_section *sec;
3359
3360 f->sections[i] = sec = arch_new_section();
3361 memset(sec, 0, sizeof(*sec));
3362
3363 sec->header = section_headers[i];
3364 sec->idx = i;
3365
Eric Andersen2bf658d2001-02-24 20:01:53 +00003366 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003367 case SHT_NULL:
3368 case SHT_NOTE:
3369 case SHT_NOBITS:
3370 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003371 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003372
3373 case SHT_PROGBITS:
3374#if LOADBITS
3375 if (!loadprogbits) {
3376 sec->contents = NULL;
3377 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003379#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003380 case SHT_SYMTAB:
3381 case SHT_STRTAB:
3382 case SHT_RELM:
3383 if (sec->header.sh_size > 0) {
3384 sec->contents = xmalloc(sec->header.sh_size);
3385 fseek(fp, sec->header.sh_offset, SEEK_SET);
3386 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3387 bb_perror_msg("error reading ELF section data");
3388 return NULL;
3389 }
3390 } else {
3391 sec->contents = NULL;
3392 }
3393 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003394
3395#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003396 case SHT_RELA:
3397 bb_error_msg("RELA relocations not supported on this architecture");
3398 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003399#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003400 case SHT_REL:
3401 bb_error_msg("REL relocations not supported on this architecture");
3402 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003403#endif
3404
Eric Andersen3b1a7442003-12-24 20:30:45 +00003405 default:
3406 if (sec->header.sh_type >= SHT_LOPROC) {
3407 /* Assume processor specific section types are debug
3408 info and can safely be ignored. If this is ever not
3409 the case (Hello MIPS?), don't put ifdefs here but
3410 create an arch_load_proc_section(). */
3411 break;
3412 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003413
Eric Andersen3b1a7442003-12-24 20:30:45 +00003414 bb_error_msg("can't handle sections of type %ld",
3415 (long) sec->header.sh_type);
3416 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003417 }
3418 }
3419
3420 /* Do what sort of interpretation as needed by each section. */
3421
3422 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3423
3424 for (i = 0; i < shnum; ++i) {
3425 struct obj_section *sec = f->sections[i];
3426 sec->name = shstrtab + sec->header.sh_name;
3427 }
3428
3429 for (i = 0; i < shnum; ++i) {
3430 struct obj_section *sec = f->sections[i];
3431
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003432 /* .modinfo should be contents only but gcc has no attribute for that.
3433 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3434 */
3435 if (strcmp(sec->name, ".modinfo") == 0)
3436 sec->header.sh_flags &= ~SHF_ALLOC;
3437
Eric Andersen9f16d612000-06-12 23:11:16 +00003438 if (sec->header.sh_flags & SHF_ALLOC)
3439 obj_insert_section_load_order(f, sec);
3440
3441 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003442 case SHT_SYMTAB:
3443 {
3444 unsigned long nsym, j;
3445 char *strtab;
3446 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003447
Eric Andersen3b1a7442003-12-24 20:30:45 +00003448 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3449 bb_error_msg("symbol size mismatch: %lu != %lu",
3450 (unsigned long) sec->header.sh_entsize,
3451 (unsigned long) sizeof(ElfW(Sym)));
3452 return NULL;
3453 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003454
Eric Andersen3b1a7442003-12-24 20:30:45 +00003455 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3456 strtab = f->sections[sec->header.sh_link]->contents;
3457 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003458
Eric Andersen3b1a7442003-12-24 20:30:45 +00003459 /* Allocate space for a table of local symbols. */
3460 j = f->local_symtab_size = sec->header.sh_info;
3461 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003462
Eric Andersen3b1a7442003-12-24 20:30:45 +00003463 /* Insert all symbols into the hash table. */
3464 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3465 ElfW(Addr) val = sym->st_value;
3466 const char *name;
3467 if (sym->st_name)
3468 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003469 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003470 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003471 else
3472 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003473
Eric Andersenbf833552003-08-13 19:56:33 +00003474#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003475 /*
3476 * For sh64 it is possible that the target of a branch
3477 * requires a mode switch (32 to 16 and back again).
3478 *
3479 * This is implied by the lsb being set in the target
3480 * address for SHmedia mode and clear for SHcompact.
3481 */
3482 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003483#endif
3484
Eric Andersen3b1a7442003-12-24 20:30:45 +00003485 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3486 val, sym->st_size);
3487 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003488 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003489 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003490
Eric Andersen3b1a7442003-12-24 20:30:45 +00003491 case SHT_RELM:
3492 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3493 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3494 (unsigned long) sec->header.sh_entsize,
3495 (unsigned long) sizeof(ElfW(RelM)));
3496 return NULL;
3497 }
3498 break;
3499 /* XXX Relocation code from modutils-2.3.19 is not here.
3500 * Why? That's about 20 lines of code from obj/obj_load.c,
3501 * which gets done in a second pass through the sections.
3502 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003503 }
3504 }
3505
3506 return f;
3507}
3508
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003509#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003510/*
3511 * load the unloaded sections directly into the memory allocated by
3512 * kernel for the module
3513 */
3514
Eric Andersenac5dbd12001-08-22 05:26:08 +00003515static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003516{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003517 ElfW(Addr) base = f->baseaddr;
3518 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003519
Eric Andersen8ae319a2001-05-21 16:09:18 +00003520 for (sec = f->load_order; sec; sec = sec->load_next) {
3521
3522 /* section already loaded? */
3523 if (sec->contents != NULL)
3524 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003525
Eric Andersen8ae319a2001-05-21 16:09:18 +00003526 if (sec->header.sh_size == 0)
3527 continue;
3528
3529 sec->contents = imagebase + (sec->header.sh_addr - base);
3530 fseek(fp, sec->header.sh_offset, SEEK_SET);
3531 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003532 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003533 return 0;
3534 }
3535
3536 }
3537 return 1;
3538}
3539#endif
3540
Eric Andersen9f16d612000-06-12 23:11:16 +00003541static void hide_special_symbols(struct obj_file *f)
3542{
3543 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003544 SPFX "cleanup_module",
3545 SPFX "init_module",
3546 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003547 NULL
3548 };
3549
3550 struct obj_symbol *sym;
3551 const char *const *p;
3552
3553 for (p = specials; *p; ++p)
3554 if ((sym = obj_find_symbol(f, *p)) != NULL)
3555 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003556 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003557}
3558
Glenn L McGrath759515c2003-08-30 06:00:33 +00003559
Eric Andersen71ae64b2002-10-10 04:20:21 +00003560#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003561static int obj_gpl_license(struct obj_file *f, const char **license)
3562{
3563 struct obj_section *sec;
3564 /* This list must match *exactly* the list of allowable licenses in
3565 * linux/include/linux/module.h. Checking for leading "GPL" will not
3566 * work, somebody will use "GPL sucks, this is proprietary".
3567 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003568 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003569 "GPL",
3570 "GPL v2",
3571 "GPL and additional rights",
3572 "Dual BSD/GPL",
3573 "Dual MPL/GPL",
3574 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003575
Eric Andersen166fa462002-09-16 05:30:24 +00003576 if ((sec = obj_find_section(f, ".modinfo"))) {
3577 const char *value, *ptr, *endptr;
3578 ptr = sec->contents;
3579 endptr = ptr + sec->header.sh_size;
3580 while (ptr < endptr) {
3581 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3582 int i;
3583 if (license)
3584 *license = value+1;
3585 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3586 if (strcmp(value+1, gpl_licenses[i]) == 0)
3587 return(0);
3588 }
3589 return(2);
3590 }
3591 if (strchr(ptr, '\0'))
3592 ptr = strchr(ptr, '\0') + 1;
3593 else
3594 ptr = endptr;
3595 }
3596 }
3597 return(1);
3598}
3599
3600#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3601#define TAINT_PROPRIETORY_MODULE (1<<0)
3602#define TAINT_FORCED_MODULE (1<<1)
3603#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003604#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003605
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003606static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003607 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3608{
3609 char buf[80];
3610 int oldval;
3611 static int first = 1;
3612 if (fd < 0 && !kernel_has_tainted)
3613 return; /* New modutils on old kernel */
3614 printf("Warning: loading %s will taint the kernel: %s%s\n",
3615 m_name, text1, text2);
3616 if (first) {
3617 printf(" See %s for information about tainted modules\n", TAINT_URL);
3618 first = 0;
3619 }
3620 if (fd >= 0) {
3621 read(fd, buf, sizeof(buf)-1);
3622 buf[sizeof(buf)-1] = '\0';
3623 oldval = strtoul(buf, NULL, 10);
3624 sprintf(buf, "%d\n", oldval | taint);
3625 write(fd, buf, strlen(buf));
3626 }
3627}
3628
3629/* Check if loading this module will taint the kernel. */
3630static void check_tainted_module(struct obj_file *f, char *m_name)
3631{
3632 static const char tainted_file[] = TAINT_FILENAME;
3633 int fd, kernel_has_tainted;
3634 const char *ptr;
3635
3636 kernel_has_tainted = 1;
3637 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3638 if (errno == ENOENT)
3639 kernel_has_tainted = 0;
3640 else if (errno == EACCES)
3641 kernel_has_tainted = 1;
3642 else {
3643 perror(tainted_file);
3644 kernel_has_tainted = 0;
3645 }
3646 }
3647
3648 switch (obj_gpl_license(f, &ptr)) {
3649 case 0:
3650 break;
3651 case 1:
3652 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3653 break;
3654 case 2:
3655 /* The module has a non-GPL license so we pretend that the
3656 * kernel always has a taint flag to get a warning even on
3657 * kernels without the proc flag.
3658 */
3659 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3660 break;
3661 default:
3662 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3663 break;
3664 }
3665
3666 if (flag_force_load)
3667 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3668
3669 if (fd >= 0)
3670 close(fd);
3671}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003672#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3673#define check_tainted_module(x, y) do { } while(0);
3674#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003675
Eric Andersen889dd202003-01-23 04:48:34 +00003676#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3677/* add module source, timestamp, kernel version and a symbol for the
3678 * start of some sections. this info is used by ksymoops to do better
3679 * debugging.
3680 */
3681static int
3682get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3683{
3684#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003685 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003686#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003687 strncpy(str, "???", sizeof(str));
3688 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003689#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3690}
3691
3692/* add module source, timestamp, kernel version and a symbol for the
3693 * start of some sections. this info is used by ksymoops to do better
3694 * debugging.
3695 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003696static void
Eric Andersen889dd202003-01-23 04:48:34 +00003697add_ksymoops_symbols(struct obj_file *f, const char *filename,
3698 const char *m_name)
3699{
3700 static const char symprefix[] = "__insmod_";
3701 struct obj_section *sec;
3702 struct obj_symbol *sym;
3703 char *name, *absolute_filename;
3704 char str[STRVERSIONLEN], real[PATH_MAX];
3705 int i, l, lm_name, lfilename, use_ksymtab, version;
3706 struct stat statbuf;
3707
3708 static const char *section_names[] = {
3709 ".text",
3710 ".rodata",
3711 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003712 ".bss",
3713 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003714 };
3715
3716 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003717 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003718 }
3719 else {
3720 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003721 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003722 errno = save_errno;
3723 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003724 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003725 }
3726
3727 lm_name = strlen(m_name);
3728 lfilename = strlen(absolute_filename);
3729
3730 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3731 * are not to be exported. otherwise leave ksymtab alone for now, the
3732 * "export all symbols" compatibility code will export these symbols later.
3733 */
3734 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3735
3736 if ((sec = obj_find_section(f, ".this"))) {
3737 /* tag the module header with the object name, last modified
3738 * timestamp and module version. worst case for module version
3739 * is 0xffffff, decimal 16777215. putting all three fields in
3740 * one symbol is less readable but saves kernel space.
3741 */
3742 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003743 lm_name+ /* module name */
3744 2+ /* "_O" */
3745 lfilename+ /* object filename */
3746 2+ /* "_M" */
3747 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3748 2+ /* "_V" */
3749 8+ /* version in dec */
3750 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003751 name = xmalloc(l);
3752 if (stat(absolute_filename, &statbuf) != 0)
3753 statbuf.st_mtime = 0;
3754 version = get_module_version(f, str); /* -1 if not found */
3755 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003756 symprefix, m_name, absolute_filename,
3757 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3758 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003759 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003760 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003761 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003762 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003763 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003764 }
3765 free(absolute_filename);
3766#ifdef _NOT_SUPPORTED_
3767 /* record where the persistent data is going, same address as previous symbol */
3768
3769 if (f->persist) {
3770 l = sizeof(symprefix)+ /* "__insmod_" */
3771 lm_name+ /* module name */
3772 2+ /* "_P" */
3773 strlen(f->persist)+ /* data store */
3774 1; /* nul */
3775 name = xmalloc(l);
3776 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003777 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003778 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003779 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003780 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003781 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003782 }
3783#endif /* _NOT_SUPPORTED_ */
3784 /* tag the desired sections if size is non-zero */
3785
3786 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3787 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003788 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003789 l = sizeof(symprefix)+ /* "__insmod_" */
3790 lm_name+ /* module name */
3791 2+ /* "_S" */
3792 strlen(sec->name)+ /* section name */
3793 2+ /* "_L" */
3794 8+ /* length in dec */
3795 1; /* nul */
3796 name = xmalloc(l);
3797 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003798 symprefix, m_name, sec->name,
3799 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003800 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003801 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003802 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003803 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003804 }
3805 }
3806}
3807#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3808
Eric Andersenbe65c352003-01-23 04:57:35 +00003809#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3810static void print_load_map(struct obj_file *f)
3811{
3812 struct obj_symbol *sym;
3813 struct obj_symbol **all, **p;
3814 struct obj_section *sec;
3815 int i, nsyms, *loaded;
3816
3817 /* Report on the section layout. */
3818
3819 printf("Sections: Size %-*s Align\n",
3820 (int) (2 * sizeof(void *)), "Address");
3821
3822 for (sec = f->load_order; sec; sec = sec->load_next) {
3823 int a;
3824 unsigned long tmp;
3825
3826 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3827 tmp >>= 1;
3828 if (a == -1)
3829 a = 0;
3830
3831 printf("%-15s %08lx %0*lx 2**%d\n",
3832 sec->name,
3833 (long)sec->header.sh_size,
3834 (int) (2 * sizeof(void *)),
3835 (long)sec->header.sh_addr,
3836 a);
3837 }
3838#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3839 /* Quick reference which section indicies are loaded. */
3840
3841 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3842 while (--i >= 0)
3843 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3844
3845 /* Collect the symbols we'll be listing. */
3846
3847 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3848 for (sym = f->symtab[i]; sym; sym = sym->next)
3849 if (sym->secidx <= SHN_HIRESERVE
3850 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3851 ++nsyms;
3852
3853 all = alloca(nsyms * sizeof(struct obj_symbol *));
3854
3855 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3856 for (sym = f->symtab[i]; sym; sym = sym->next)
3857 if (sym->secidx <= SHN_HIRESERVE
3858 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3859 *p++ = sym;
3860
3861 /* And list them. */
3862 printf("\nSymbols:\n");
3863 for (p = all; p < all + nsyms; ++p) {
3864 char type = '?';
3865 unsigned long value;
3866
3867 sym = *p;
3868 if (sym->secidx == SHN_ABS) {
3869 type = 'A';
3870 value = sym->value;
3871 } else if (sym->secidx == SHN_UNDEF) {
3872 type = 'U';
3873 value = 0;
3874 } else {
3875 sec = f->sections[sym->secidx];
3876
3877 if (sec->header.sh_type == SHT_NOBITS)
3878 type = 'B';
3879 else if (sec->header.sh_flags & SHF_ALLOC) {
3880 if (sec->header.sh_flags & SHF_EXECINSTR)
3881 type = 'T';
3882 else if (sec->header.sh_flags & SHF_WRITE)
3883 type = 'D';
3884 else
3885 type = 'R';
3886 }
3887 value = sym->value + sec->header.sh_addr;
3888 }
3889
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003890 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003891 type = tolower(type);
3892
3893 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3894 type, sym->name);
3895 }
3896#endif
3897}
3898
3899#endif
3900
Eric Andersen9f16d612000-06-12 23:11:16 +00003901extern int insmod_main( int argc, char **argv)
3902{
Eric Andersena18aaf12001-01-24 19:07:09 +00003903 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003904 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003905 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003906 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003907 unsigned long m_size;
3908 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003909 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003910 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003911 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003912 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003913 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003914#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003915 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003916 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003917 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003919#ifdef CONFIG_FEATURE_CLEAN_UP
3920 FILE *fp = 0;
3921#else
3922 FILE *fp;
3923#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003924#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3925 int flag_print_load_map = 0;
3926#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003927 int k_version = 0;
3928 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003929
Erik Andersene49d5ec2000-02-08 19:58:47 +00003930 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003931#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003932 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003933#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003934 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003935#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003936 {
3937 switch (opt) {
3938 case 'f': /* force loading */
3939 flag_force_load = 1;
3940 break;
3941 case 'k': /* module loaded by kerneld, auto-cleanable */
3942 flag_autoclean = 1;
3943 break;
3944 case 's': /* log to syslog */
3945 /* log to syslog -- not supported */
3946 /* but kernel needs this for request_module(), */
3947 /* as this calls: modprobe -k -s -- <module> */
3948 /* so silently ignore this flag */
3949 break;
3950 case 'v': /* verbose output */
3951 flag_verbose = 1;
3952 break;
3953 case 'q': /* silent */
3954 flag_quiet = 1;
3955 break;
3956 case 'x': /* do not export externs */
3957 flag_export = 0;
3958 break;
3959 case 'o': /* name the output module */
3960 free(m_name);
3961 m_name = bb_xstrdup(optarg);
3962 break;
3963 case 'L': /* Stub warning */
3964 /* This is needed for compatibility with modprobe.
3965 * In theory, this does locking, but we don't do
3966 * that. So be careful and plan your life around not
3967 * loading the same module 50 times concurrently. */
3968 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003969#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003970 case 'm': /* print module load map */
3971 flag_print_load_map = 1;
3972 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003973#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003974 default:
3975 bb_show_usage();
3976 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003977 }
Eric Andersen03d80912003-12-19 21:04:19 +00003978
Eric Andersena18aaf12001-01-24 19:07:09 +00003979 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003980 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003981 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003982
Erik Andersene49d5ec2000-02-08 19:58:47 +00003983 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003984 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003985 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003986 len = strlen(tmp);
3987
Eric Andersen03d80912003-12-19 21:04:19 +00003988 if (uname(&myuname) == 0) {
3989 if (myuname.release[0] == '2') {
3990 k_version = myuname.release[2] - '0';
3991 }
3992 }
3993
3994#if defined(CONFIG_FEATURE_2_6_MODULES)
3995 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003996 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003997 len-=3;
3998 tmp[len] = '\0';
3999 }
4000 else
4001#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004002 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4003 len-=2;
4004 tmp[len] = '\0';
4005 }
Eric Andersen2d342152002-06-18 05:16:25 +00004006
Eric Andersen03d80912003-12-19 21:04:19 +00004007
4008#if defined(CONFIG_FEATURE_2_6_MODULES)
4009 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004010 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004011 else
Eric Andersen03d80912003-12-19 21:04:19 +00004012#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004013 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004014
Eric Andersen61f83052002-06-22 17:15:42 +00004015 if (!m_name) {
4016 m_name = tmp;
4017 } else {
4018 free(tmp1);
4019 tmp1 = 0; /* flag for free(m_name) before exit() */
4020 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004021
Eric Andersen14d35432001-05-14 17:07:32 +00004022 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004023 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4024 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004025 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4026 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004027 if (k_version) { /* uname succeedd */
4028 char *module_dir;
4029 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004030 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004031
Eric Andersen03d80912003-12-19 21:04:19 +00004032 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004033 /* Jump through hoops in case /lib/modules/`uname -r`
4034 * is a symlink. We do not want recursive_action to
4035 * follow symlinks, but we do want to follow the
4036 * /lib/modules/`uname -r` dir, So resolve it ourselves
4037 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004038 if (realpath (tmdn, real_module_dir) == NULL)
4039 module_dir = tmdn;
4040 else
4041 module_dir = real_module_dir;
4042 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004043 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004044 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004045 }
4046
4047 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004048 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004049 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004050 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004051
Eric Andersen03d80912003-12-19 21:04:19 +00004052 free(m_filename);
4053 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004054 if (realpath (_PATH_MODULES, module_dir) == NULL)
4055 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004056 /* No module found under /lib/modules/`uname -r`, this
4057 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004058 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004059 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004060 {
Eric Andersen61f83052002-06-22 17:15:42 +00004061 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004062 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004063 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004064 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004065 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004066 }
4067 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004068 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004069 }
Eric Andersen03d80912003-12-19 21:04:19 +00004070 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004071 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004072
Rob Landley999af202005-12-11 20:14:12 +00004073 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004074 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004075
Eric Andersene7047882003-12-11 01:42:13 +00004076#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004077 if (k_version > 4)
4078 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004079 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004080 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004081 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004082 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004083#endif
4084
Eric Andersen8ae319a2001-05-21 16:09:18 +00004085 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004086 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004087
Eric Andersen9f16d612000-06-12 23:11:16 +00004088 if (get_modinfo_value(f, "kernel_version") == NULL)
4089 m_has_modinfo = 0;
4090 else
4091 m_has_modinfo = 1;
4092
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004093#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004094 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004095 if (!flag_quiet) {
4096 if (uname(&uts_info) < 0)
4097 uts_info.release[0] = '\0';
4098 if (m_has_modinfo) {
4099 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004100 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004101 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004102 "compiled for");
4103 goto out;
4104 }
4105 }
4106
4107 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4108 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004109 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004110 "\t%s was compiled for kernel version %s\n"
4111 "\twhile this kernel is version %s",
4112 m_filename, m_strversion, uts_info.release);
4113 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004114 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004115 "\t%s was compiled for kernel version %s\n"
4116 "\twhile this kernel is version %s.",
4117 m_filename, m_strversion, uts_info.release);
4118 goto out;
4119 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004120 }
4121 }
4122 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004123#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004124
Eric Andersencb3b9b12004-06-22 11:50:52 +00004125 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004126 if (!new_get_kernel_symbols())
4127 goto out;
4128 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004129 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004130 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004131 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004132 }
4133
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004134#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004135 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004136 if (m_has_modinfo)
4137 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004138
4139 if (m_crcs != k_crcs)
4140 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004141#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004142
Erik Andersene49d5ec2000-02-08 19:58:47 +00004143 /* Let the module know about the kernel symbols. */
4144 add_kernel_symbols(f);
4145
Eric Andersen9f16d612000-06-12 23:11:16 +00004146 /* Allocate common symbols, symbol tables, and string tables. */
4147
Eric Andersencb3b9b12004-06-22 11:50:52 +00004148 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004149 {
4150 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004151 }
4152
Eric Andersen9f16d612000-06-12 23:11:16 +00004153 if (!obj_check_undefineds(f)) {
4154 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004155 }
4156 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004157 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004158
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004159 /* done with the module name, on to the optional var=value arguments */
4160 ++optind;
4161
Eric Andersen9f16d612000-06-12 23:11:16 +00004162 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004163 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004164 {
4165 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004166 }
4167 }
4168
Eric Andersen9f16d612000-06-12 23:11:16 +00004169 arch_create_got(f);
4170 hide_special_symbols(f);
4171
Eric Andersen889dd202003-01-23 04:48:34 +00004172#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4173 add_ksymoops_symbols(f, m_filename, m_name);
4174#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4175
Eric Andersencb3b9b12004-06-22 11:50:52 +00004176 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004177
Erik Andersene49d5ec2000-02-08 19:58:47 +00004178 /* Find current size of the module */
4179 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004180
4181
Erik Andersene49d5ec2000-02-08 19:58:47 +00004182 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004183 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004184 case EEXIST:
4185 bb_error_msg("A module named %s already exists", m_name);
4186 goto out;
4187 case ENOMEM:
4188 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4189 m_size);
4190 goto out;
4191 default:
4192 bb_perror_msg("create_module: %s", m_name);
4193 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004194 }
Erik Andersend387d011999-12-21 02:55:11 +00004195
Eric Andersen8ae319a2001-05-21 16:09:18 +00004196#if !LOADBITS
4197 /*
4198 * the PROGBITS section was not loaded by the obj_load
4199 * now we can load them directly into the kernel memory
4200 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004201 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004202 delete_module(m_name);
4203 goto out;
4204 }
Eric Andersen03d80912003-12-19 21:04:19 +00004205#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004206
Eric Andersen9f16d612000-06-12 23:11:16 +00004207 if (!obj_relocate(f, m_addr)) {
4208 delete_module(m_name);
4209 goto out;
4210 }
Erik Andersend387d011999-12-21 02:55:11 +00004211
Eric Andersencb3b9b12004-06-22 11:50:52 +00004212 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004213 {
4214 delete_module(m_name);
4215 goto out;
4216 }
4217
Eric Andersenbe65c352003-01-23 04:57:35 +00004218#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4219 if(flag_print_load_map)
4220 print_load_map(f);
4221#endif
4222
Matt Kraai3e856ce2000-12-01 02:55:13 +00004223 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004224
4225out:
Eric Andersen61f83052002-06-22 17:15:42 +00004226#ifdef CONFIG_FEATURE_CLEAN_UP
4227 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004228 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004229 if(tmp1) {
4230 free(tmp1);
4231 } else {
4232 free(m_name);
4233 }
4234 free(m_filename);
4235#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004236 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004237}
Eric Andersene7047882003-12-11 01:42:13 +00004238
4239
4240#endif
4241
4242
4243#ifdef CONFIG_FEATURE_2_6_MODULES
4244
4245#include <sys/mman.h>
4246#include <asm/unistd.h>
4247#include <sys/syscall.h>
4248
4249/* We use error numbers in a loose translation... */
4250static const char *moderror(int err)
4251{
4252 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004253 case ENOEXEC:
4254 return "Invalid module format";
4255 case ENOENT:
4256 return "Unknown symbol in module";
4257 case ESRCH:
4258 return "Module has wrong symbol version";
4259 case EINVAL:
4260 return "Invalid parameters";
4261 default:
4262 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004263 }
4264}
4265
4266extern int insmod_ng_main( int argc, char **argv)
4267{
4268 int i;
4269 int fd;
4270 long int ret;
4271 struct stat st;
4272 unsigned long len;
4273 void *map;
4274 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004275
Eric Andersene7047882003-12-11 01:42:13 +00004276 filename = argv[1];
4277 if (!filename) {
4278 bb_show_usage();
4279 return -1;
4280 }
4281
4282 /* Rest is options */
4283 for (i = 2; i < argc; i++) {
4284 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4285 /* Spaces handled by "" pairs, but no way of escaping quotes */
4286 if (strchr(argv[i], ' ')) {
4287 strcat(options, "\"");
4288 strcat(options, argv[i]);
4289 strcat(options, "\"");
4290 } else {
4291 strcat(options, argv[i]);
4292 }
4293 strcat(options, " ");
4294 }
4295
4296 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4297 bb_perror_msg_and_die("cannot open module `%s'", filename);
4298 }
4299
4300 fstat(fd, &st);
4301 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004302 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004303 if (map == MAP_FAILED) {
4304 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4305 }
4306
4307 ret = syscall(__NR_init_module, map, len, options);
4308 if (ret != 0) {
4309 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004310 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004311 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004312
Eric Andersene7047882003-12-11 01:42:13 +00004313 return 0;
4314}
4315
4316#endif