blob: d1504d0abb103963b9d0d0bf8e78e8a3a7690f9f [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
Eric Andersen45a05132004-09-02 23:03:25 +0000220/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000221#if defined(__powerpc64__)
222#define MATCH_MACHINE(x) (x == EM_PPC64)
223#define SHT_RELM SHT_RELA
224#define Elf64_RelM Elf64_Rela
225#define ELFCLASSM ELFCLASS64
226#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000227#define MATCH_MACHINE(x) (x == EM_PPC)
228#define SHT_RELM SHT_RELA
229#define Elf32_RelM Elf32_Rela
230#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000231#define CONFIG_USE_PLT_ENTRIES
232#define CONFIG_PLT_ENTRY_SIZE 16
233#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000234#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000235#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000236#define ARCHDATAM "__ftr_fixup"
237#endif
238
Eric Andersen45a05132004-09-02 23:03:25 +0000239/* S390 */
240#if defined(__s390__)
241#define MATCH_MACHINE(x) (x == EM_S390)
242#define SHT_RELM SHT_RELA
243#define Elf32_RelM Elf32_Rela
244#define ELFCLASSM ELFCLASS32
245#define CONFIG_USE_PLT_ENTRIES
246#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000247#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000248#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000249#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000250#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000251
Eric Andersen45a05132004-09-02 23:03:25 +0000252/* SuperH */
253#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000254#define MATCH_MACHINE(x) (x == EM_SH)
255#define SHT_RELM SHT_RELA
256#define Elf32_RelM Elf32_Rela
257#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000258#define CONFIG_USE_GOT_ENTRIES
259#define CONFIG_GOT_ENTRY_SIZE 4
260#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000261/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000262/* I'm not sure about big endian, so let's warn: */
Eric Andersenbf833552003-08-13 19:56:33 +0000263#if defined(__sh__) && defined(__BIG_ENDIAN__)
264#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000265#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000266/* it may or may not work on the SH1/SH2... Error on those also */
267#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000268#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000269#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000270#endif
271
Eric Andersen45a05132004-09-02 23:03:25 +0000272/* Sparc */
273#if defined(__sparc__)
274#define MATCH_MACHINE(x) (x == EM_SPARC)
275#define SHT_RELM SHT_RELA
276#define Elf32_RelM Elf32_Rela
277#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000278#endif
279
Eric Andersen45a05132004-09-02 23:03:25 +0000280/* v850e */
281#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000282#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
283#define SHT_RELM SHT_RELA
284#define Elf32_RelM Elf32_Rela
285#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000286#define CONFIG_USE_PLT_ENTRIES
287#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000288#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000289#ifndef EM_CYGNUS_V850 /* grumble */
290#define EM_CYGNUS_V850 0x9080
291#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000292#define SYMBOL_PREFIX "_"
293#endif
294
Eric Andersen45a05132004-09-02 23:03:25 +0000295/* X86_64 */
296#if defined(__x86_64__)
297#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000298#define SHT_RELM SHT_RELA
Mike Frysinger91fbdac2005-10-02 06:44:39 +0000299#define CONFIG_USE_GOT_ENTRIES
300#define CONFIG_GOT_ENTRY_SIZE 8
301#define CONFIG_USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000302#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000303#define ELFCLASSM ELFCLASS64
304#endif
305
Eric Andersencffd5022002-05-24 06:50:15 +0000306#ifndef SHT_RELM
307#error Sorry, but insmod.c does not yet support this architecture...
308#endif
309
310
Eric Andersen9f16d612000-06-12 23:11:16 +0000311//----------------------------------------------------------------------------
312//--------modutils module.h, lines 45-242
313//----------------------------------------------------------------------------
314
315/* Definitions for the Linux module syscall interface.
316 Copyright 1996, 1997 Linux International.
317
318 Contributed by Richard Henderson <rth@tamu.edu>
319
320 This file is part of the Linux modutils.
321
322 This program is free software; you can redistribute it and/or modify it
323 under the terms of the GNU General Public License as published by the
324 Free Software Foundation; either version 2 of the License, or (at your
325 option) any later version.
326
327 This program is distributed in the hope that it will be useful, but
328 WITHOUT ANY WARRANTY; without even the implied warranty of
329 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
330 General Public License for more details.
331
332 You should have received a copy of the GNU General Public License
333 along with this program; if not, write to the Free Software Foundation,
334 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
335
336
337#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000338static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000339
Mike Frysinger63654c12004-12-26 09:13:32 +0000340#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000341
342/*======================================================================*/
343/* For sizeof() which are related to the module platform and not to the
344 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
345
346#define tgt_sizeof_char sizeof(char)
347#define tgt_sizeof_short sizeof(short)
348#define tgt_sizeof_int sizeof(int)
349#define tgt_sizeof_long sizeof(long)
350#define tgt_sizeof_char_p sizeof(char *)
351#define tgt_sizeof_void_p sizeof(void *)
352#define tgt_long long
353
354#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
355#undef tgt_sizeof_long
356#undef tgt_sizeof_char_p
357#undef tgt_sizeof_void_p
358#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000359static const int tgt_sizeof_long = 8;
360static const int tgt_sizeof_char_p = 8;
361static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000362#define tgt_long long long
363#endif
364
365/*======================================================================*/
366/* The structures used in Linux 2.1. */
367
368/* Note: new_module_symbol does not use tgt_long intentionally */
369struct new_module_symbol
370{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000371 unsigned long value;
372 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000373};
374
375struct new_module_persist;
376
377struct new_module_ref
378{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000379 unsigned tgt_long dep; /* kernel addresses */
380 unsigned tgt_long ref;
381 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000382};
383
384struct new_module
385{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000386 unsigned tgt_long size_of_struct; /* == sizeof(module) */
387 unsigned tgt_long next;
388 unsigned tgt_long name;
389 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000390
Eric Andersen3b1a7442003-12-24 20:30:45 +0000391 tgt_long usecount;
392 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000393
Eric Andersen3b1a7442003-12-24 20:30:45 +0000394 unsigned nsyms;
395 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000396
Eric Andersen3b1a7442003-12-24 20:30:45 +0000397 unsigned tgt_long syms;
398 unsigned tgt_long deps;
399 unsigned tgt_long refs;
400 unsigned tgt_long init;
401 unsigned tgt_long cleanup;
402 unsigned tgt_long ex_table_start;
403 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000406#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000407 /* Everything after here is extension. */
408 unsigned tgt_long persist_start;
409 unsigned tgt_long persist_end;
410 unsigned tgt_long can_unload;
411 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000412 const char *kallsyms_start; /* All symbols for kernel debugging */
413 const char *kallsyms_end;
414 const char *archdata_start; /* arch specific data for module */
415 const char *archdata_end;
416 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000417};
418
Eric Andersencffd5022002-05-24 06:50:15 +0000419#ifdef ARCHDATAM
420#define ARCHDATA_SEC_NAME ARCHDATAM
421#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000422#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000423#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000424#define KALLSYMS_SEC_NAME "__kallsyms"
425
426
Eric Andersen9f16d612000-06-12 23:11:16 +0000427struct new_module_info
428{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000429 unsigned long addr;
430 unsigned long size;
431 unsigned long flags;
432 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000433};
434
435/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000436static const int NEW_MOD_RUNNING = 1;
437static const int NEW_MOD_DELETED = 2;
438static const int NEW_MOD_AUTOCLEAN = 4;
439static const int NEW_MOD_VISITED = 8;
440static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000441
Eric Andersencb3b9b12004-06-22 11:50:52 +0000442int init_module(const char *name, const struct new_module *);
443int query_module(const char *name, int which, void *buf,
444 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000445
446/* Values for query_module's which. */
447
Mark Whitley59ab0252001-01-23 22:30:04 +0000448static const int QM_MODULES = 1;
449static const int QM_DEPS = 2;
450static const int QM_REFS = 3;
451static const int QM_SYMBOLS = 4;
452static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
454/*======================================================================*/
455/* The system calls unchanged between 2.0 and 2.1. */
456
457unsigned long create_module(const char *, size_t);
458int delete_module(const char *);
459
460
461#endif /* module.h */
462
463//----------------------------------------------------------------------------
464//--------end of modutils module.h
465//----------------------------------------------------------------------------
466
467
468
469//----------------------------------------------------------------------------
470//--------modutils obj.h, lines 253-462
471//----------------------------------------------------------------------------
472
473/* Elf object file loading and relocation routines.
474 Copyright 1996, 1997 Linux International.
475
476 Contributed by Richard Henderson <rth@tamu.edu>
477
478 This file is part of the Linux modutils.
479
480 This program is free software; you can redistribute it and/or modify it
481 under the terms of the GNU General Public License as published by the
482 Free Software Foundation; either version 2 of the License, or (at your
483 option) any later version.
484
485 This program is distributed in the hope that it will be useful, but
486 WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 General Public License for more details.
489
490 You should have received a copy of the GNU General Public License
491 along with this program; if not, write to the Free Software Foundation,
492 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
493
494
495#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000496static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000497
Mike Frysinger63654c12004-12-26 09:13:32 +0000498#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000499
500/* The relocatable object is manipulated using elfin types. */
501
502#include <stdio.h>
503#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000504#include <endian.h>
505
506#if __BYTE_ORDER == __LITTLE_ENDIAN
507#define ELFDATAM ELFDATA2LSB
508#elif __BYTE_ORDER == __BIG_ENDIAN
509#define ELFDATAM ELFDATA2MSB
510#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000511
Eric Andersen9f16d612000-06-12 23:11:16 +0000512#ifndef ElfW
513# if ELFCLASSM == ELFCLASS32
514# define ElfW(x) Elf32_ ## x
515# define ELFW(x) ELF32_ ## x
516# else
517# define ElfW(x) Elf64_ ## x
518# define ELFW(x) ELF64_ ## x
519# endif
520#endif
521
Eric Andersen85e5e722003-07-22 08:56:55 +0000522/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000523#ifndef ELF32_ST_INFO
524# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
525#endif
526
527#ifndef ELF64_ST_INFO
528# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
529#endif
530
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000531#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
532#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
533#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
534#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
535#define ELF_R_SYM(val) ELFW(R_SYM)(val)
536
Eric Andersen9f16d612000-06-12 23:11:16 +0000537struct obj_string_patch;
538struct obj_symbol_patch;
539
540struct obj_section
541{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000542 ElfW(Shdr) header;
543 const char *name;
544 char *contents;
545 struct obj_section *load_next;
546 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000547};
548
549struct obj_symbol
550{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000551 struct obj_symbol *next; /* hash table link */
552 const char *name;
553 unsigned long value;
554 unsigned long size;
555 int secidx; /* the defining section index/module */
556 int info;
557 int ksymidx; /* for export to the kernel symtab */
558 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000559};
560
561/* Hardcode the hash table size. We shouldn't be needing so many
562 symbols that we begin to degrade performance, and we get a big win
563 by giving the compiler a constant divisor. */
564
565#define HASH_BUCKETS 521
566
567struct obj_file
568{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000569 ElfW(Ehdr) header;
570 ElfW(Addr) baseaddr;
571 struct obj_section **sections;
572 struct obj_section *load_order;
573 struct obj_section **load_order_search_start;
574 struct obj_string_patch *string_patches;
575 struct obj_symbol_patch *symbol_patches;
576 int (*symbol_cmp)(const char *, const char *);
577 unsigned long (*symbol_hash)(const char *);
578 unsigned long local_symtab_size;
579 struct obj_symbol **local_symtab;
580 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000581};
582
583enum obj_reloc
584{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000585 obj_reloc_ok,
586 obj_reloc_overflow,
587 obj_reloc_dangerous,
588 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000589};
590
591struct obj_string_patch
592{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000593 struct obj_string_patch *next;
594 int reloc_secidx;
595 ElfW(Addr) reloc_offset;
596 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000597};
598
599struct obj_symbol_patch
600{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000601 struct obj_symbol_patch *next;
602 int reloc_secidx;
603 ElfW(Addr) reloc_offset;
604 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000605};
606
607
608/* Generic object manipulation routines. */
609
Eric Andersen044228d2001-07-17 01:12:36 +0000610static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000611
Eric Andersen044228d2001-07-17 01:12:36 +0000612static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000613
Eric Andersen044228d2001-07-17 01:12:36 +0000614static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000615 const char *name);
616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000618 struct obj_symbol *sym);
619
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000620#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000621static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000622 int (*cmp)(const char *, const char *),
623 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000624#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 const char *name);
628
Eric Andersen044228d2001-07-17 01:12:36 +0000629static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000630 struct obj_section *sec);
631
Eric Andersen044228d2001-07-17 01:12:36 +0000632static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000633 const char *name,
634 unsigned long align,
635 unsigned long size);
636
Eric Andersen044228d2001-07-17 01:12:36 +0000637static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000638 const char *name,
639 unsigned long align,
640 unsigned long size);
641
Eric Andersen044228d2001-07-17 01:12:36 +0000642static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000645 const char *string);
646
Eric Andersen044228d2001-07-17 01:12:36 +0000647static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000648 struct obj_symbol *sym);
649
Eric Andersen044228d2001-07-17 01:12:36 +0000650static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Eric Andersen044228d2001-07-17 01:12:36 +0000652static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000653
Eric Andersen044228d2001-07-17 01:12:36 +0000654static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000655
Eric Andersen044228d2001-07-17 01:12:36 +0000656static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
662/* Architecture specific manipulation routines. */
663
Eric Andersen044228d2001-07-17 01:12:36 +0000664static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000665
Eric Andersen044228d2001-07-17 01:12:36 +0000666static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000667
Eric Andersen044228d2001-07-17 01:12:36 +0000668static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000669
Eric Andersen044228d2001-07-17 01:12:36 +0000670static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000671 struct obj_section *targsec,
672 struct obj_section *symsec,
673 struct obj_symbol *sym,
674 ElfW(RelM) *rel, ElfW(Addr) value);
675
Eric Andersencffd5022002-05-24 06:50:15 +0000676static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000677
Glenn L McGrath759515c2003-08-30 06:00:33 +0000678static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000679
Eric Andersen9f16d612000-06-12 23:11:16 +0000680#endif /* obj.h */
681//----------------------------------------------------------------------------
682//--------end of modutils obj.h
683//----------------------------------------------------------------------------
684
685
Miles Baderae28b042002-04-01 09:34:25 +0000686/* SPFX is always a string, so it can be concatenated to string constants. */
687#ifdef SYMBOL_PREFIX
688#define SPFX SYMBOL_PREFIX
689#else
690#define SPFX ""
691#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000692
Erik Andersen02104321999-12-17 18:57:34 +0000693
Erik Andersend387d011999-12-21 02:55:11 +0000694#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000695static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000696
Eric Andersen9f16d612000-06-12 23:11:16 +0000697/*======================================================================*/
698
Eric Andersen044228d2001-07-17 01:12:36 +0000699static int flag_force_load = 0;
700static int flag_autoclean = 0;
701static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000702static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000703static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000704
705
706/*======================================================================*/
707
Eric Andersencffd5022002-05-24 06:50:15 +0000708#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000709
Eric Andersencffd5022002-05-24 06:50:15 +0000710struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000711{
Eric Andersencffd5022002-05-24 06:50:15 +0000712 struct arch_list_entry *next;
713 CONFIG_LIST_ARCHTYPE addend;
714 int offset;
715 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000716};
Eric Andersencffd5022002-05-24 06:50:15 +0000717
Eric Andersen21adca72000-12-06 18:18:26 +0000718#endif
719
Eric Andersencffd5022002-05-24 06:50:15 +0000720#if defined(CONFIG_USE_SINGLE)
721
722struct arch_single_entry
723{
Eric Andersen9f16d612000-06-12 23:11:16 +0000724 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000725 int inited : 1;
726 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000727};
Eric Andersencffd5022002-05-24 06:50:15 +0000728
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000729#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000730
Eric Andersen2bf658d2001-02-24 20:01:53 +0000731#if defined(__mips__)
732struct mips_hi16
733{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000734 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000735 ElfW(Addr) *addr;
736 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000737};
738#endif
739
Eric Andersenfe4208f2000-09-24 03:44:29 +0000740struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000741 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000742#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000743 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000744#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000745#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000747#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000748#if defined(__mips__)
749 struct mips_hi16 *mips_hi16_list;
750#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000751};
752
Eric Andersenfe4208f2000-09-24 03:44:29 +0000753struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000755#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000756#if defined(CONFIG_USE_PLT_LIST)
757 struct arch_list_entry *pltent;
758#else
759 struct arch_single_entry pltent;
760#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000761#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000762#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000763 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000764#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000765};
766
767
Eric Andersen9f16d612000-06-12 23:11:16 +0000768struct external_module {
769 const char *name;
770 ElfW(Addr) addr;
771 int used;
772 size_t nsyms;
773 struct new_module_symbol *syms;
774};
775
Eric Andersen044228d2001-07-17 01:12:36 +0000776static struct new_module_symbol *ksyms;
777static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000778
Eric Andersen044228d2001-07-17 01:12:36 +0000779static struct external_module *ext_modules;
780static int n_ext_modules;
781static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000782extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000783
Eric Andersen61f83052002-06-22 17:15:42 +0000784static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000785static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000786
Eric Andersenfe4208f2000-09-24 03:44:29 +0000787
Erik Andersen02104321999-12-17 18:57:34 +0000788
Eric Andersen9f16d612000-06-12 23:11:16 +0000789/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000790
Eric Andersen9f16d612000-06-12 23:11:16 +0000791
Eric Andersen14d35432001-05-14 17:07:32 +0000792static int check_module_name_match(const char *filename, struct stat *statbuf,
793 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000794{
Eric Andersen14d35432001-05-14 17:07:32 +0000795 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000796
Eric Andersen14d35432001-05-14 17:07:32 +0000797 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000798 return (FALSE);
799 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000800 char *tmp, *tmp1 = bb_xstrdup(filename);
801 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000802 if (strcmp(tmp, fullname) == 0) {
803 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000804 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000805 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000806 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000807 }
Eric Andersen14d35432001-05-14 17:07:32 +0000808 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000809 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000810 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000811}
812
Erik Andersen02104321999-12-17 18:57:34 +0000813
Eric Andersen9f16d612000-06-12 23:11:16 +0000814/*======================================================================*/
815
Eric Andersen044228d2001-07-17 01:12:36 +0000816static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000817{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000818 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000819 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000820
Eric Andersencffd5022002-05-24 06:50:15 +0000821 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000822
Eric Andersen9f16d612000-06-12 23:11:16 +0000823 return &f->root;
824}
825
Eric Andersen044228d2001-07-17 01:12:36 +0000826static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000827{
828 return xmalloc(sizeof(struct obj_section));
829}
830
Eric Andersen044228d2001-07-17 01:12:36 +0000831static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000832{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000833 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000834 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000835
Eric Andersencffd5022002-05-24 06:50:15 +0000836 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000837
Eric Andersen9f16d612000-06-12 23:11:16 +0000838 return &sym->root;
839}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000840
Eric Andersen044228d2001-07-17 01:12:36 +0000841static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000842arch_apply_relocation(struct obj_file *f,
843 struct obj_section *targsec,
844 struct obj_section *symsec,
845 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000846 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000847{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000848 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000849 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000850 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
851 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000852#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
853 struct arch_symbol *isym = (struct arch_symbol *) sym;
854#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000855#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000856 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000857#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000858#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000859 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000860 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000861# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000862 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000863# else
Eric Andersencffd5022002-05-24 06:50:15 +0000864 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000865# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000866#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000867
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000868 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000869
Eric Andersencffd5022002-05-24 06:50:15 +0000870#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000871
Eric Andersen3b1a7442003-12-24 20:30:45 +0000872 case R_ARM_NONE:
873 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000874
Eric Andersen3b1a7442003-12-24 20:30:45 +0000875 case R_ARM_ABS32:
876 *loc += v;
877 break;
Miles Baderae28b042002-04-01 09:34:25 +0000878
Eric Andersen3b1a7442003-12-24 20:30:45 +0000879 case R_ARM_GOT32:
880 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000881
Eric Andersen3b1a7442003-12-24 20:30:45 +0000882 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000883 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
884 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 assert(got);
888 *loc += got - dot;
889 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000890
Eric Andersen3b1a7442003-12-24 20:30:45 +0000891 case R_ARM_PC24:
892 case R_ARM_PLT32:
893 goto bb_use_plt;
894
895 case R_ARM_GOTOFF: /* address relative to the got */
896 assert(got);
897 *loc += v - got;
898 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000899
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000900#elif defined(__cris__)
901
902 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000903 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000904
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000905 case R_CRIS_32:
906 /* CRIS keeps the relocation value in the r_addend field and
907 * should not use whats in *loc at all
908 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000909 *loc = v;
910 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000911
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000912#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000913
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000914 case R_H8_DIR24R8:
915 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
916 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000917 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000918 case R_H8_DIR24A8:
919 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000920 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000921 case R_H8_DIR32:
922 case R_H8_DIR32A16:
923 *loc += v;
924 break;
925 case R_H8_PCREL16:
926 v -= dot + 2;
927 if ((ElfW(Sword))v > 0x7fff ||
928 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
929 ret = obj_reloc_overflow;
930 else
931 *(unsigned short *)loc = v;
932 break;
933 case R_H8_PCREL8:
934 v -= dot + 1;
935 if ((ElfW(Sword))v > 0x7f ||
936 (ElfW(Sword))v < -(ElfW(Sword))0x80)
937 ret = obj_reloc_overflow;
938 else
939 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000940 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000941
Eric Andersencffd5022002-05-24 06:50:15 +0000942#elif defined(__i386__)
943
Eric Andersen3b1a7442003-12-24 20:30:45 +0000944 case R_386_NONE:
945 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000946
Eric Andersen3b1a7442003-12-24 20:30:45 +0000947 case R_386_32:
948 *loc += v;
949 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000950
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 case R_386_PLT32:
952 case R_386_PC32:
953 *loc += v - dot;
954 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000955
Eric Andersen3b1a7442003-12-24 20:30:45 +0000956 case R_386_GLOB_DAT:
957 case R_386_JMP_SLOT:
958 *loc = v;
959 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000960
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 case R_386_RELATIVE:
962 *loc += f->baseaddr;
963 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000964
Eric Andersen3b1a7442003-12-24 20:30:45 +0000965 case R_386_GOTPC:
966 assert(got != 0);
967 *loc += got - dot;
968 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000969
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 case R_386_GOT32:
971 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000972
Eric Andersen3b1a7442003-12-24 20:30:45 +0000973 case R_386_GOTOFF:
974 assert(got != 0);
975 *loc += v - got;
976 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000977
978#elif defined(__mc68000__)
979
Eric Andersen3b1a7442003-12-24 20:30:45 +0000980 case R_68K_NONE:
981 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000982
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 case R_68K_32:
984 *loc += v;
985 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000986
Eric Andersen3b1a7442003-12-24 20:30:45 +0000987 case R_68K_8:
988 if (v > 0xff) {
989 ret = obj_reloc_overflow;
990 }
991 *(char *)loc = v;
992 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000993
Eric Andersen3b1a7442003-12-24 20:30:45 +0000994 case R_68K_16:
995 if (v > 0xffff) {
996 ret = obj_reloc_overflow;
997 }
998 *(short *)loc = v;
999 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001000
Eric Andersen3b1a7442003-12-24 20:30:45 +00001001 case R_68K_PC8:
1002 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001003 if ((ElfW(Sword))v > 0x7f ||
1004 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001005 ret = obj_reloc_overflow;
1006 }
1007 *(char *)loc = v;
1008 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001009
Eric Andersen3b1a7442003-12-24 20:30:45 +00001010 case R_68K_PC16:
1011 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001012 if ((ElfW(Sword))v > 0x7fff ||
1013 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001014 ret = obj_reloc_overflow;
1015 }
1016 *(short *)loc = v;
1017 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001018
Eric Andersen3b1a7442003-12-24 20:30:45 +00001019 case R_68K_PC32:
1020 *(int *)loc = v - dot;
1021 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001022
Eric Andersen3b1a7442003-12-24 20:30:45 +00001023 case R_68K_GLOB_DAT:
1024 case R_68K_JMP_SLOT:
1025 *loc = v;
1026 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001027
Eric Andersen3b1a7442003-12-24 20:30:45 +00001028 case R_68K_RELATIVE:
1029 *(int *)loc += f->baseaddr;
1030 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001031
Eric Andersen3b1a7442003-12-24 20:30:45 +00001032 case R_68K_GOT32:
1033 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001034
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001035# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001036 case R_68K_GOTOFF:
1037 assert(got != 0);
1038 *loc += v - got;
1039 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001040# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001041
1042#elif defined(__mips__)
1043
Eric Andersen3b1a7442003-12-24 20:30:45 +00001044 case R_MIPS_NONE:
1045 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001046
Eric Andersen3b1a7442003-12-24 20:30:45 +00001047 case R_MIPS_32:
1048 *loc += v;
1049 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001050
Eric Andersen3b1a7442003-12-24 20:30:45 +00001051 case R_MIPS_26:
1052 if (v % 4)
1053 ret = obj_reloc_dangerous;
1054 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1055 ret = obj_reloc_overflow;
1056 *loc =
1057 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1058 0x03ffffff);
1059 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001060
Eric Andersen3b1a7442003-12-24 20:30:45 +00001061 case R_MIPS_HI16:
1062 {
1063 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001064
Eric Andersen3b1a7442003-12-24 20:30:45 +00001065 /* We cannot relocate this one now because we don't know the value
1066 of the carry we need to add. Save the information, and let LO16
1067 do the actual relocation. */
1068 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1069 n->addr = loc;
1070 n->value = v;
1071 n->next = ifile->mips_hi16_list;
1072 ifile->mips_hi16_list = n;
1073 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001074 }
1075
Eric Andersen3b1a7442003-12-24 20:30:45 +00001076 case R_MIPS_LO16:
1077 {
1078 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001079 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080
1081 /* Sign extend the addend we extract from the lo insn. */
1082 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1083
1084 if (ifile->mips_hi16_list != NULL) {
1085 struct mips_hi16 *l;
1086
1087 l = ifile->mips_hi16_list;
1088 while (l != NULL) {
1089 struct mips_hi16 *next;
1090 unsigned long insn;
1091
1092 /* The value for the HI16 had best be the same. */
1093 assert(v == l->value);
1094
1095 /* Do the HI16 relocation. Note that we actually don't
1096 need to know anything about the LO16 itself, except where
1097 to find the low 16 bits of the addend needed by the LO16. */
1098 insn = *l->addr;
1099 val =
1100 ((insn & 0xffff) << 16) +
1101 vallo;
1102 val += v;
1103
1104 /* Account for the sign extension that will happen in the
1105 low bits. */
1106 val =
1107 ((val >> 16) +
1108 ((val & 0x8000) !=
1109 0)) & 0xffff;
1110
1111 insn = (insn & ~0xffff) | val;
1112 *l->addr = insn;
1113
1114 next = l->next;
1115 free(l);
1116 l = next;
1117 }
1118
1119 ifile->mips_hi16_list = NULL;
1120 }
1121
1122 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1123 val = v + vallo;
1124 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1125 *loc = insnlo;
1126 break;
1127 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001128
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001129#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001130
Eric Andersen3b1a7442003-12-24 20:30:45 +00001131 case R_PPC_ADDR16_HA:
1132 *(unsigned short *)loc = (v + 0x8000) >> 16;
1133 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001134
Eric Andersen3b1a7442003-12-24 20:30:45 +00001135 case R_PPC_ADDR16_HI:
1136 *(unsigned short *)loc = v >> 16;
1137 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001138
Eric Andersen3b1a7442003-12-24 20:30:45 +00001139 case R_PPC_ADDR16_LO:
1140 *(unsigned short *)loc = v;
1141 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001142
Eric Andersen3b1a7442003-12-24 20:30:45 +00001143 case R_PPC_REL24:
1144 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001145
Eric Andersen3b1a7442003-12-24 20:30:45 +00001146 case R_PPC_REL32:
1147 *loc = v - dot;
1148 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001149
Eric Andersen3b1a7442003-12-24 20:30:45 +00001150 case R_PPC_ADDR32:
1151 *loc = v;
1152 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001153
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001154#elif defined(__s390__)
1155
1156 case R_390_32:
1157 *(unsigned int *) loc += v;
1158 break;
1159 case R_390_16:
1160 *(unsigned short *) loc += v;
1161 break;
1162 case R_390_8:
1163 *(unsigned char *) loc += v;
1164 break;
1165
1166 case R_390_PC32:
1167 *(unsigned int *) loc += v - dot;
1168 break;
1169 case R_390_PC16DBL:
1170 *(unsigned short *) loc += (v - dot) >> 1;
1171 break;
1172 case R_390_PC16:
1173 *(unsigned short *) loc += v - dot;
1174 break;
1175
1176 case R_390_PLT32:
1177 case R_390_PLT16DBL:
1178 /* find the plt entry and initialize it. */
1179 assert(isym != NULL);
1180 pe = (struct arch_single_entry *) &isym->pltent;
1181 assert(pe->allocated);
1182 if (pe->inited == 0) {
1183 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1184 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1185 ip[1] = 0x100607f1;
1186 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1187 ip[2] = v - 2;
1188 else
1189 ip[2] = v;
1190 pe->inited = 1;
1191 }
1192
1193 /* Insert relative distance to target. */
1194 v = plt + pe->offset - dot;
1195 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1196 *(unsigned int *) loc = (unsigned int) v;
1197 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1198 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1199 break;
1200
1201 case R_390_GLOB_DAT:
1202 case R_390_JMP_SLOT:
1203 *loc = v;
1204 break;
1205
1206 case R_390_RELATIVE:
1207 *loc += f->baseaddr;
1208 break;
1209
1210 case R_390_GOTPC:
1211 assert(got != 0);
1212 *(unsigned long *) loc += got - dot;
1213 break;
1214
1215 case R_390_GOT12:
1216 case R_390_GOT16:
1217 case R_390_GOT32:
1218 assert(isym != NULL);
1219 assert(got != 0);
1220 if (!isym->gotent.inited)
1221 {
1222 isym->gotent.inited = 1;
1223 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1224 }
1225 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1226 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1227 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1228 *(unsigned short *) loc += isym->gotent.offset;
1229 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1230 *(unsigned int *) loc += isym->gotent.offset;
1231 break;
1232
1233# ifndef R_390_GOTOFF32
1234# define R_390_GOTOFF32 R_390_GOTOFF
1235# endif
1236 case R_390_GOTOFF32:
1237 assert(got != 0);
1238 *loc += v - got;
1239 break;
1240
Eric Andersencffd5022002-05-24 06:50:15 +00001241#elif defined(__sh__)
1242
Eric Andersen3b1a7442003-12-24 20:30:45 +00001243 case R_SH_NONE:
1244 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001245
Eric Andersen3b1a7442003-12-24 20:30:45 +00001246 case R_SH_DIR32:
1247 *loc += v;
1248 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001249
Eric Andersen3b1a7442003-12-24 20:30:45 +00001250 case R_SH_REL32:
1251 *loc += v - dot;
1252 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001253
Eric Andersen3b1a7442003-12-24 20:30:45 +00001254 case R_SH_PLT32:
1255 *loc = v - dot;
1256 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001257
Eric Andersen3b1a7442003-12-24 20:30:45 +00001258 case R_SH_GLOB_DAT:
1259 case R_SH_JMP_SLOT:
1260 *loc = v;
1261 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001262
Eric Andersen3b1a7442003-12-24 20:30:45 +00001263 case R_SH_RELATIVE:
1264 *loc = f->baseaddr + rel->r_addend;
1265 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001266
Eric Andersen3b1a7442003-12-24 20:30:45 +00001267 case R_SH_GOTPC:
1268 assert(got != 0);
1269 *loc = got - dot + rel->r_addend;
1270 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001271
Eric Andersen3b1a7442003-12-24 20:30:45 +00001272 case R_SH_GOT32:
1273 goto bb_use_got;
1274
1275 case R_SH_GOTOFF:
1276 assert(got != 0);
1277 *loc = v - got;
1278 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001279
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001280# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001281 case R_SH_IMM_MEDLOW16:
1282 case R_SH_IMM_LOW16:
1283 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001284 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001285
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001286 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001287 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001288
Eric Andersen3b1a7442003-12-24 20:30:45 +00001289 /*
1290 * movi and shori have the format:
1291 *
1292 * | op | imm | reg | reserved |
1293 * 31..26 25..10 9.. 4 3 .. 0
1294 *
1295 * so we simply mask and or in imm.
1296 */
1297 word = *loc & ~0x3fffc00;
1298 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001299
Eric Andersen3b1a7442003-12-24 20:30:45 +00001300 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001301
Eric Andersen3b1a7442003-12-24 20:30:45 +00001302 break;
1303 }
Eric Andersenbf833552003-08-13 19:56:33 +00001304
Eric Andersen3b1a7442003-12-24 20:30:45 +00001305 case R_SH_IMM_MEDLOW16_PCREL:
1306 case R_SH_IMM_LOW16_PCREL:
1307 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001308 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001309
Eric Andersen3b1a7442003-12-24 20:30:45 +00001310 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001311
Eric Andersen3b1a7442003-12-24 20:30:45 +00001312 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001313
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001314 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001315 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001316
Eric Andersen3b1a7442003-12-24 20:30:45 +00001317 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001318
Eric Andersen3b1a7442003-12-24 20:30:45 +00001319 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001320
Eric Andersen3b1a7442003-12-24 20:30:45 +00001321 break;
1322 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001323# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001324
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001325#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001326
Eric Andersen3b1a7442003-12-24 20:30:45 +00001327 case R_V850_NONE:
1328 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001329
Eric Andersen3b1a7442003-12-24 20:30:45 +00001330 case R_V850_32:
1331 /* We write two shorts instead of a long because even
1332 32-bit insns only need half-word alignment, but
1333 32-bit data needs to be long-word aligned. */
1334 v += ((unsigned short *)loc)[0];
1335 v += ((unsigned short *)loc)[1] << 16;
1336 ((unsigned short *)loc)[0] = v & 0xffff;
1337 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1338 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001339
Eric Andersen3b1a7442003-12-24 20:30:45 +00001340 case R_V850_22_PCREL:
1341 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001342
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001343#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001344
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001345 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001346 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001347
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001348 case R_X86_64_64:
1349 *loc += v;
1350 break;
1351
1352 case R_X86_64_32:
1353 *(unsigned int *) loc += v;
1354 if (v > 0xffffffff)
1355 {
1356 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1357 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1358 }
1359 break;
1360
1361 case R_X86_64_32S:
1362 *(signed int *) loc += v;
1363 break;
1364
1365 case R_X86_64_16:
1366 *(unsigned short *) loc += v;
1367 break;
1368
1369 case R_X86_64_8:
1370 *(unsigned char *) loc += v;
1371 break;
1372
1373 case R_X86_64_PC32:
1374 *(unsigned int *) loc += v - dot;
1375 break;
1376
1377 case R_X86_64_PC16:
1378 *(unsigned short *) loc += v - dot;
1379 break;
1380
1381 case R_X86_64_PC8:
1382 *(unsigned char *) loc += v - dot;
1383 break;
1384
1385 case R_X86_64_GLOB_DAT:
1386 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001387 *loc = v;
1388 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001389
1390 case R_X86_64_RELATIVE:
1391 *loc += f->baseaddr;
1392 break;
1393
1394 case R_X86_64_GOT32:
1395 case R_X86_64_GOTPCREL:
1396 goto bb_use_got;
1397# if 0
1398 assert(isym != NULL);
1399 if (!isym->gotent.reloc_done)
1400 {
1401 isym->gotent.reloc_done = 1;
1402 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1403 }
1404 /* XXX are these really correct? */
1405 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1406 *(unsigned int *) loc += v + isym->gotent.offset;
1407 else
1408 *loc += isym->gotent.offset;
1409 break;
1410# endif
1411
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001412#endif
1413
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001414 default:
1415 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1416 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001417 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001418
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001419#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001420
Eric Andersen3b1a7442003-12-24 20:30:45 +00001421bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001422
Eric Andersen3b1a7442003-12-24 20:30:45 +00001423 /* find the plt entry and initialize it if necessary */
1424 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001425
Eric Andersencffd5022002-05-24 06:50:15 +00001426#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001427 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1428 pe = pe->next;
1429 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001430#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001431 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001432#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001433
Eric Andersen3b1a7442003-12-24 20:30:45 +00001434 if (! pe->inited) {
1435 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001436
Eric Andersen3b1a7442003-12-24 20:30:45 +00001437 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001438
1439#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001440 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1441 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001442#endif
1443#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001444 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001445 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001446 ip[2] = 0x7d6903a6; /* mtctr r11 */
1447 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001448#endif
Miles Baderae28b042002-04-01 09:34:25 +00001449#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001450 /* We have to trash a register, so we assume that any control
1451 transfer more than 21-bits away must be a function call
1452 (so we can use a call-clobbered register). */
1453 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1454 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001455#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001456 pe->inited = 1;
1457 }
Eric Andersen21adca72000-12-06 18:18:26 +00001458
Eric Andersen3b1a7442003-12-24 20:30:45 +00001459 /* relative distance to target */
1460 v -= dot;
1461 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001462#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001463 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001464#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001465 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001466#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001467 /* go via the plt */
1468 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001469
1470#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001472#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001474#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001476
Eric Andersen3b1a7442003-12-24 20:30:45 +00001477 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001478#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 /* Convert to words. */
1480 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001481
Eric Andersen3b1a7442003-12-24 20:30:45 +00001482 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001483#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001484#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001485 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001486#endif
Miles Baderae28b042002-04-01 09:34:25 +00001487#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 /* We write two shorts instead of a long because even 32-bit insns
1489 only need half-word alignment, but the 32-bit data write needs
1490 to be long-word aligned. */
1491 ((unsigned short *)loc)[0] =
1492 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1493 | ((v >> 16) & 0x3f); /* offs high part */
1494 ((unsigned short *)loc)[1] =
1495 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001496#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001497 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001498#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001499
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001500#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001501bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001502
Eric Andersen3b1a7442003-12-24 20:30:45 +00001503 assert(isym != NULL);
1504 /* needs an entry in the .got: set it, once */
1505 if (!isym->gotent.inited) {
1506 isym->gotent.inited = 1;
1507 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1508 }
1509 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001510#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001511 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001512#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001513 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001514#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001515 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001516
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001517#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001518 }
1519
1520 return ret;
1521}
1522
Eric Andersencffd5022002-05-24 06:50:15 +00001523
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001524#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001525
1526static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1527 int offset, int size)
1528{
1529 struct arch_list_entry *pe;
1530
1531 for (pe = *list; pe != NULL; pe = pe->next) {
1532 if (pe->addend == rel->r_addend) {
1533 break;
1534 }
1535 }
1536
1537 if (pe == NULL) {
1538 pe = xmalloc(sizeof(struct arch_list_entry));
1539 pe->next = *list;
1540 pe->addend = rel->r_addend;
1541 pe->offset = offset;
1542 pe->inited = 0;
1543 *list = pe;
1544 return size;
1545 }
1546 return 0;
1547}
1548
1549#endif
1550
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001551#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001552
1553static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1554 int offset, int size)
1555{
1556 if (single->allocated == 0) {
1557 single->allocated = 1;
1558 single->offset = offset;
1559 single->inited = 0;
1560 return size;
1561 }
1562 return 0;
1563}
1564
1565#endif
1566
1567#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1568
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001569static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001570 int offset, int size)
1571{
1572 struct obj_section *myrelsec = obj_find_section(f, name);
1573
1574 if (offset == 0) {
1575 offset += size;
1576 }
1577
1578 if (myrelsec) {
1579 obj_extend_section(myrelsec, offset);
1580 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001581 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001582 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001583 assert(myrelsec);
1584 }
1585
1586 return myrelsec;
1587}
1588
1589#endif
1590
1591static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001592{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001593#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001594 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001595 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001596#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001597 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001598#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001599#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001600 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001601#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001602 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001603 ElfW(RelM) *rel, *relend;
1604 ElfW(Sym) *symtab, *extsym;
1605 const char *strtab, *name;
1606 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001607
Eric Andersen21adca72000-12-06 18:18:26 +00001608 for (i = 0; i < f->header.e_shnum; ++i) {
1609 relsec = f->sections[i];
1610 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001611 continue;
1612
Eric Andersen21adca72000-12-06 18:18:26 +00001613 symsec = f->sections[relsec->header.sh_link];
1614 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001615
Eric Andersen21adca72000-12-06 18:18:26 +00001616 rel = (ElfW(RelM) *) relsec->contents;
1617 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1618 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001619 strtab = (const char *) strsec->contents;
1620
1621 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001622 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001623
Eric Andersencffd5022002-05-24 06:50:15 +00001624#if defined(CONFIG_USE_GOT_ENTRIES)
1625 got_allocate = 0;
1626#endif
1627#if defined(CONFIG_USE_PLT_ENTRIES)
1628 plt_allocate = 0;
1629#endif
1630
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001631 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001632#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633 case R_ARM_PC24:
1634 case R_ARM_PLT32:
1635 plt_allocate = 1;
1636 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001637
Eric Andersen3b1a7442003-12-24 20:30:45 +00001638 case R_ARM_GOTOFF:
1639 case R_ARM_GOTPC:
1640 got_needed = 1;
1641 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001642
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 case R_ARM_GOT32:
1644 got_allocate = 1;
1645 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001646
Eric Andersen21adca72000-12-06 18:18:26 +00001647#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 case R_386_GOTPC:
1649 case R_386_GOTOFF:
1650 got_needed = 1;
1651 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001652
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 case R_386_GOT32:
1654 got_allocate = 1;
1655 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001656
1657#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 case R_PPC_REL24:
1659 plt_allocate = 1;
1660 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001661
1662#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663 case R_68K_GOT32:
1664 got_allocate = 1;
1665 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001666
Eric Andersen16451a02004-03-19 12:16:18 +00001667#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001668 case R_68K_GOTOFF:
1669 got_needed = 1;
1670 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001671#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001672
1673#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001675 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001677
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 case R_SH_GOTPC:
1679 case R_SH_GOTOFF:
1680 got_needed = 1;
1681 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001682
1683#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 case R_V850_22_PCREL:
1685 plt_needed = 1;
1686 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001687
1688#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001689 default:
1690 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001691 }
1692
Eric Andersen21adca72000-12-06 18:18:26 +00001693 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001694 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001695 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001696 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001697 }
1698 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001699#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001700 if (got_allocate) {
1701 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001702 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001703 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001704
1705 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001706 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001707#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001708#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001709 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001710#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001711 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001712 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001713 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001714#else
1715 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001716 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001717 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001718#endif
1719 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001720 }
1721#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001722 }
Miles Baderae28b042002-04-01 09:34:25 +00001723 }
Eric Andersen21adca72000-12-06 18:18:26 +00001724
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001725#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001726 if (got_needed) {
1727 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001728 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001729 }
Eric Andersen21adca72000-12-06 18:18:26 +00001730#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001731
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001732#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001733 if (plt_needed) {
1734 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001735 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001736 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001737#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001738
1739#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001740}
1741
Eric Andersen9f16d612000-06-12 23:11:16 +00001742/*======================================================================*/
1743
1744/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001745static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001746{
1747 unsigned long h = 0;
1748 unsigned long g;
1749 unsigned char ch;
1750
1751 while (n > 0) {
1752 ch = *name++;
1753 h = (h << 4) + ch;
1754 if ((g = (h & 0xf0000000)) != 0) {
1755 h ^= g >> 24;
1756 h &= ~g;
1757 }
1758 n--;
1759 }
1760 return h;
1761}
1762
Eric Andersen044228d2001-07-17 01:12:36 +00001763static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001764{
1765 return obj_elf_hash_n(name, strlen(name));
1766}
1767
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001768#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001769/* String comparison for non-co-versioned kernel and module. */
1770
1771static int ncv_strcmp(const char *a, const char *b)
1772{
1773 size_t alen = strlen(a), blen = strlen(b);
1774
1775 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1776 return strncmp(a, b, alen);
1777 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1778 return strncmp(a, b, blen);
1779 else
1780 return strcmp(a, b);
1781}
1782
1783/* String hashing for non-co-versioned kernel and module. Here
1784 we are simply forced to drop the crc from the hash. */
1785
1786static unsigned long ncv_symbol_hash(const char *str)
1787{
1788 size_t len = strlen(str);
1789 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1790 len -= 10;
1791 return obj_elf_hash_n(str, len);
1792}
1793
Eric Andersen044228d2001-07-17 01:12:36 +00001794static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001795obj_set_symbol_compare(struct obj_file *f,
1796 int (*cmp) (const char *, const char *),
1797 unsigned long (*hash) (const char *))
1798{
1799 if (cmp)
1800 f->symbol_cmp = cmp;
1801 if (hash) {
1802 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1803 int i;
1804
1805 f->symbol_hash = hash;
1806
1807 memcpy(tmptab, f->symtab, sizeof(tmptab));
1808 memset(f->symtab, 0, sizeof(f->symtab));
1809
1810 for (i = 0; i < HASH_BUCKETS; ++i)
1811 for (sym = tmptab[i]; sym; sym = next) {
1812 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1813 next = sym->next;
1814 sym->next = f->symtab[h];
1815 f->symtab[h] = sym;
1816 }
1817 }
1818}
1819
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001820#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001821
Eric Andersen044228d2001-07-17 01:12:36 +00001822static struct obj_symbol *
1823obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001824 unsigned long symidx, int info,
1825 int secidx, ElfW(Addr) value,
1826 unsigned long size)
1827{
1828 struct obj_symbol *sym;
1829 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001830 int n_type = ELF_ST_TYPE(info);
1831 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00001832
1833 for (sym = f->symtab[hash]; sym; sym = sym->next)
1834 if (f->symbol_cmp(sym->name, name) == 0) {
1835 int o_secidx = sym->secidx;
1836 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001837 int o_type = ELF_ST_TYPE(o_info);
1838 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00001839
1840 /* A redefinition! Is it legal? */
1841
1842 if (secidx == SHN_UNDEF)
1843 return sym;
1844 else if (o_secidx == SHN_UNDEF)
1845 goto found;
1846 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1847 /* Cope with local and global symbols of the same name
1848 in the same object file, as might have been created
1849 by ld -r. The only reason locals are now seen at this
1850 level at all is so that we can do semi-sensible things
1851 with parameters. */
1852
1853 struct obj_symbol *nsym, **p;
1854
1855 nsym = arch_new_symbol();
1856 nsym->next = sym->next;
1857 nsym->ksymidx = -1;
1858
1859 /* Excise the old (local) symbol from the hash chain. */
1860 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1861 continue;
1862 *p = sym = nsym;
1863 goto found;
1864 } else if (n_binding == STB_LOCAL) {
1865 /* Another symbol of the same name has already been defined.
1866 Just add this to the local table. */
1867 sym = arch_new_symbol();
1868 sym->next = NULL;
1869 sym->ksymidx = -1;
1870 f->local_symtab[symidx] = sym;
1871 goto found;
1872 } else if (n_binding == STB_WEAK)
1873 return sym;
1874 else if (o_binding == STB_WEAK)
1875 goto found;
1876 /* Don't unify COMMON symbols with object types the programmer
1877 doesn't expect. */
1878 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001879 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001880 return sym;
1881 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001882 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001883 goto found;
1884 else {
1885 /* Don't report an error if the symbol is coming from
1886 the kernel or some external module. */
1887 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001888 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001889 return sym;
1890 }
1891 }
1892
1893 /* Completely new symbol. */
1894 sym = arch_new_symbol();
1895 sym->next = f->symtab[hash];
1896 f->symtab[hash] = sym;
1897 sym->ksymidx = -1;
1898
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001899 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00001900 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001901 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001902 name, (long) symidx, (long) f->local_symtab_size);
1903 else
1904 f->local_symtab[symidx] = sym;
1905 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001906
Eric Andersen3b1a7442003-12-24 20:30:45 +00001907found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001908 sym->name = name;
1909 sym->value = value;
1910 sym->size = size;
1911 sym->secidx = secidx;
1912 sym->info = info;
1913
1914 return sym;
1915}
1916
Eric Andersen044228d2001-07-17 01:12:36 +00001917static struct obj_symbol *
1918obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001919{
1920 struct obj_symbol *sym;
1921 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1922
1923 for (sym = f->symtab[hash]; sym; sym = sym->next)
1924 if (f->symbol_cmp(sym->name, name) == 0)
1925 return sym;
1926
1927 return NULL;
1928}
1929
Eric Andersen044228d2001-07-17 01:12:36 +00001930static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001931 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1932{
1933 if (sym) {
1934 if (sym->secidx >= SHN_LORESERVE)
1935 return sym->value;
1936
1937 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1938 } else {
1939 /* As a special case, a NULL sym has value zero. */
1940 return 0;
1941 }
1942}
1943
Eric Andersen044228d2001-07-17 01:12:36 +00001944static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001945{
1946 int i, n = f->header.e_shnum;
1947
1948 for (i = 0; i < n; ++i)
1949 if (strcmp(f->sections[i]->name, name) == 0)
1950 return f->sections[i];
1951
1952 return NULL;
1953}
1954
1955static int obj_load_order_prio(struct obj_section *a)
1956{
1957 unsigned long af, ac;
1958
1959 af = a->header.sh_flags;
1960
1961 ac = 0;
1962 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001963 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001964 ac |= 32;
1965 if (af & SHF_ALLOC)
1966 ac |= 16;
1967 if (!(af & SHF_WRITE))
1968 ac |= 8;
1969 if (af & SHF_EXECINSTR)
1970 ac |= 4;
1971 if (a->header.sh_type != SHT_NOBITS)
1972 ac |= 2;
1973
1974 return ac;
1975}
1976
Eric Andersen044228d2001-07-17 01:12:36 +00001977static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001978obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1979{
1980 struct obj_section **p;
1981 int prio = obj_load_order_prio(sec);
1982 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1983 if (obj_load_order_prio(*p) < prio)
1984 break;
1985 sec->load_next = *p;
1986 *p = sec;
1987}
1988
Eric Andersen044228d2001-07-17 01:12:36 +00001989static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001990 const char *name,
1991 unsigned long align,
1992 unsigned long size)
1993{
1994 int newidx = f->header.e_shnum++;
1995 struct obj_section *sec;
1996
1997 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1998 f->sections[newidx] = sec = arch_new_section();
1999
2000 memset(sec, 0, sizeof(*sec));
2001 sec->header.sh_type = SHT_PROGBITS;
2002 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2003 sec->header.sh_size = size;
2004 sec->header.sh_addralign = align;
2005 sec->name = name;
2006 sec->idx = newidx;
2007 if (size)
2008 sec->contents = xmalloc(size);
2009
2010 obj_insert_section_load_order(f, sec);
2011
2012 return sec;
2013}
2014
Eric Andersen044228d2001-07-17 01:12:36 +00002015static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002016 const char *name,
2017 unsigned long align,
2018 unsigned long size)
2019{
2020 int newidx = f->header.e_shnum++;
2021 struct obj_section *sec;
2022
2023 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2024 f->sections[newidx] = sec = arch_new_section();
2025
2026 memset(sec, 0, sizeof(*sec));
2027 sec->header.sh_type = SHT_PROGBITS;
2028 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2029 sec->header.sh_size = size;
2030 sec->header.sh_addralign = align;
2031 sec->name = name;
2032 sec->idx = newidx;
2033 if (size)
2034 sec->contents = xmalloc(size);
2035
2036 sec->load_next = f->load_order;
2037 f->load_order = sec;
2038 if (f->load_order_search_start == &f->load_order)
2039 f->load_order_search_start = &sec->load_next;
2040
2041 return sec;
2042}
2043
Eric Andersen044228d2001-07-17 01:12:36 +00002044static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002045{
2046 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002047 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002048 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2049 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002050 return sec->contents + oldsize;
2051}
2052
2053
Eric Andersen9f16d612000-06-12 23:11:16 +00002054/* Conditionally add the symbols from the given symbol set to the
2055 new module. */
2056
2057static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002058add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002059 int idx, struct new_module_symbol *syms, size_t nsyms)
2060{
2061 struct new_module_symbol *s;
2062 size_t i;
2063 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002064#ifdef SYMBOL_PREFIX
2065 char *name_buf = 0;
2066 size_t name_alloced_size = 0;
2067#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002068#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2069 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002070
Glenn L McGrath759515c2003-08-30 06:00:33 +00002071 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002072#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002073 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002074 /* Only add symbols that are already marked external.
2075 If we override locals we may cause problems for
2076 argument initialization. We will also create a false
2077 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002078 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002079 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002080
Glenn L McGrath759515c2003-08-30 06:00:33 +00002081 /* GPL licensed modules can use symbols exported with
2082 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2083 * exported names. Non-GPL modules never see any GPLONLY_
2084 * symbols so they cannot fudge it by adding the prefix on
2085 * their references.
2086 */
2087 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002088#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002089 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002090 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002091 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002092#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002093 continue;
2094 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002095 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002096
Miles Baderae28b042002-04-01 09:34:25 +00002097#ifdef SYMBOL_PREFIX
2098 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2099 kernel exports `C names', but module object files
2100 reference `linker names'). */
2101 size_t extra = sizeof SYMBOL_PREFIX;
2102 size_t name_size = strlen (name) + extra;
2103 if (name_size > name_alloced_size) {
2104 name_alloced_size = name_size * 2;
2105 name_buf = alloca (name_alloced_size);
2106 }
2107 strcpy (name_buf, SYMBOL_PREFIX);
2108 strcpy (name_buf + extra - 1, name);
2109 name = name_buf;
2110#endif /* SYMBOL_PREFIX */
2111
2112 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002113 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002114#ifdef SYMBOL_PREFIX
2115 /* Put NAME_BUF into more permanent storage. */
2116 name = xmalloc (name_size);
2117 strcpy (name, name_buf);
2118#endif
2119 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002120 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002121 STT_NOTYPE),
2122 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002123 /* Did our symbol just get installed? If so, mark the
2124 module as "used". */
2125 if (sym->secidx == idx)
2126 used = 1;
2127 }
2128 }
2129
2130 return used;
2131}
2132
2133static void add_kernel_symbols(struct obj_file *f)
2134{
2135 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002136 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002137
2138 /* Add module symbols first. */
2139
2140 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2141 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002142 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2143 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002144
2145 n_ext_modules_used = nused;
2146
2147 /* And finally the symbols from the kernel proper. */
2148
2149 if (nksyms)
2150 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2151}
2152
2153static char *get_modinfo_value(struct obj_file *f, const char *key)
2154{
2155 struct obj_section *sec;
2156 char *p, *v, *n, *ep;
2157 size_t klen = strlen(key);
2158
2159 sec = obj_find_section(f, ".modinfo");
2160 if (sec == NULL)
2161 return NULL;
2162 p = sec->contents;
2163 ep = p + sec->header.sh_size;
2164 while (p < ep) {
2165 v = strchr(p, '=');
2166 n = strchr(p, '\0');
2167 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002168 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002169 return v + 1;
2170 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002171 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002172 return n;
2173 }
2174 p = n + 1;
2175 }
2176
2177 return NULL;
2178}
2179
2180
2181/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002182/* Functions relating to module loading after 2.1.18. */
2183
2184static int
2185new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2186{
2187 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002188 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002189 struct obj_symbol *sym;
2190 char *contents, *loc;
2191 int min, max, n;
2192
2193 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002194 if ((q = strchr(p, '=')) == NULL) {
2195 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002196 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002197 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002198
2199 key = alloca(q - p + 6);
2200 memcpy(key, "parm_", 5);
2201 memcpy(key + 5, p, q - p);
2202 key[q - p + 5] = 0;
2203
2204 p = get_modinfo_value(f, key);
2205 key += 5;
2206 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002207 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002208 return 0;
2209 }
2210
Miles Baderae28b042002-04-01 09:34:25 +00002211#ifdef SYMBOL_PREFIX
2212 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2213 strcpy (sym_name, SYMBOL_PREFIX);
2214 strcat (sym_name, key);
2215#else
2216 sym_name = key;
2217#endif
2218 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002219
2220 /* Also check that the parameter was not resolved from the kernel. */
2221 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002222 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002223 return 0;
2224 }
2225
2226 if (isdigit(*p)) {
2227 min = strtoul(p, &p, 10);
2228 if (*p == '-')
2229 max = strtoul(p + 1, &p, 10);
2230 else
2231 max = min;
2232 } else
2233 min = max = 1;
2234
2235 contents = f->sections[sym->secidx]->contents;
2236 loc = contents + sym->value;
2237 n = (*++q != '\0');
2238
2239 while (1) {
2240 if ((*p == 's') || (*p == 'c')) {
2241 char *str;
2242
2243 /* Do C quoting if we begin with a ", else slurp the lot. */
2244 if (*q == '"') {
2245 char *r;
2246
2247 str = alloca(strlen(q));
2248 for (r = str, q++; *q != '"'; ++q, ++r) {
2249 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002250 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002251 key);
2252 return 0;
2253 } else if (*q == '\\')
2254 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002255 case 'a':
2256 *r = '\a';
2257 break;
2258 case 'b':
2259 *r = '\b';
2260 break;
2261 case 'e':
2262 *r = '\033';
2263 break;
2264 case 'f':
2265 *r = '\f';
2266 break;
2267 case 'n':
2268 *r = '\n';
2269 break;
2270 case 'r':
2271 *r = '\r';
2272 break;
2273 case 't':
2274 *r = '\t';
2275 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002276
Eric Andersen3b1a7442003-12-24 20:30:45 +00002277 case '0':
2278 case '1':
2279 case '2':
2280 case '3':
2281 case '4':
2282 case '5':
2283 case '6':
2284 case '7':
2285 {
2286 int c = *q - '0';
2287 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002288 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002289 if (q[1] >= '0' && q[1] <= '7')
2290 c = (c * 8) + *++q - '0';
2291 }
2292 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002293 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002294 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002295
Eric Andersen3b1a7442003-12-24 20:30:45 +00002296 default:
2297 *r = *q;
2298 break;
2299 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002300 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002301 }
2302 *r = '\0';
2303 ++q;
2304 } else {
2305 char *r;
2306
2307 /* In this case, the string is not quoted. We will break
2308 it using the coma (like for ints). If the user wants to
2309 include comas in a string, he just has to quote it */
2310
2311 /* Search the next coma */
2312 r = strchr(q, ',');
2313
2314 /* Found ? */
2315 if (r != (char *) NULL) {
2316 /* Recopy the current field */
2317 str = alloca(r - q + 1);
2318 memcpy(str, q, r - q);
2319
Eric Andersenaff114c2004-04-14 17:51:38 +00002320 /* I don't know if it is useful, as the previous case
2321 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002322 str[r - q] = '\0';
2323
2324 /* Keep next fields */
2325 q = r;
2326 } else {
2327 /* last string */
2328 str = q;
2329 q = "";
2330 }
2331 }
2332
2333 if (*p == 's') {
2334 /* Normal string */
2335 obj_string_patch(f, sym->secidx, loc - contents, str);
2336 loc += tgt_sizeof_char_p;
2337 } else {
2338 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002339 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002340
2341 /* Get the size of each member */
2342 /* Probably we should do that outside the loop ? */
2343 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002344 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002345 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002346 return 0;
2347 }
2348 charssize = strtoul(p + 1, (char **) NULL, 10);
2349
2350 /* Check length */
2351 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002352 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002353 charssize - 1);
2354 return 0;
2355 }
2356
2357 /* Copy to location */
2358 strcpy((char *) loc, str);
2359 loc += charssize;
2360 }
2361 } else {
2362 long v = strtoul(q, &q, 0);
2363 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002364 case 'b':
2365 *loc++ = v;
2366 break;
2367 case 'h':
2368 *(short *) loc = v;
2369 loc += tgt_sizeof_short;
2370 break;
2371 case 'i':
2372 *(int *) loc = v;
2373 loc += tgt_sizeof_int;
2374 break;
2375 case 'l':
2376 *(long *) loc = v;
2377 loc += tgt_sizeof_long;
2378 break;
2379
2380 default:
2381 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2382 return 0;
2383 }
2384 }
2385
2386retry_end_of_value:
2387 switch (*q) {
2388 case '\0':
2389 goto end_of_arg;
2390
2391 case ' ':
2392 case '\t':
2393 case '\n':
2394 case '\r':
2395 ++q;
2396 goto retry_end_of_value;
2397
2398 case ',':
2399 if (++n > max) {
2400 bb_error_msg("too many values for %s (max %d)", key, max);
2401 return 0;
2402 }
2403 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002404 break;
2405
2406 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002407 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002408 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002409 }
2410 }
2411
Eric Andersen3b1a7442003-12-24 20:30:45 +00002412end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002413 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002414 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002415 return 0;
2416 }
2417
2418 argc--, argv++;
2419 }
2420
2421 return 1;
2422}
2423
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002424#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002425static int new_is_module_checksummed(struct obj_file *f)
2426{
2427 const char *p = get_modinfo_value(f, "using_checksums");
2428 if (p)
2429 return atoi(p);
2430 else
2431 return 0;
2432}
2433
2434/* Get the module's kernel version in the canonical integer form. */
2435
2436static int
2437new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2438{
2439 char *p, *q;
2440 int a, b, c;
2441
2442 p = get_modinfo_value(f, "kernel_version");
2443 if (p == NULL)
2444 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002445 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002446
2447 a = strtoul(p, &p, 10);
2448 if (*p != '.')
2449 return -1;
2450 b = strtoul(p + 1, &p, 10);
2451 if (*p != '.')
2452 return -1;
2453 c = strtoul(p + 1, &q, 10);
2454 if (p + 1 == q)
2455 return -1;
2456
2457 return a << 16 | b << 8 | c;
2458}
2459
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002460#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002461
2462
Eric Andersen9f16d612000-06-12 23:11:16 +00002463/* Fetch the loaded modules, and all currently exported symbols. */
2464
2465static int new_get_kernel_symbols(void)
2466{
2467 char *module_names, *mn;
2468 struct external_module *modules, *m;
2469 struct new_module_symbol *syms, *s;
2470 size_t ret, bufsize, nmod, nsyms, i, j;
2471
2472 /* Collect the loaded modules. */
2473
2474 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002475retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002476 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002477 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002478 module_names = xrealloc(module_names, bufsize = ret);
2479 goto retry_modules_load;
2480 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002481 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002482 return 0;
2483 }
2484
2485 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002486
2487 /* Collect the modules' symbols. */
2488
Mark Whitley94fd4802001-03-12 23:08:34 +00002489 if (nmod){
2490 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2491 memset(modules, 0, nmod * sizeof(*modules));
2492 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002493 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002494 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002495
Mark Whitley94fd4802001-03-12 23:08:34 +00002496 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2497 if (errno == ENOENT) {
2498 /* The module was removed out from underneath us. */
2499 continue;
2500 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002501 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002502 return 0;
2503 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002504
Mark Whitley94fd4802001-03-12 23:08:34 +00002505 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002506retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002507 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2508 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002509 case ENOSPC:
2510 syms = xrealloc(syms, bufsize = ret);
2511 goto retry_mod_sym_load;
2512 case ENOENT:
2513 /* The module was removed out from underneath us. */
2514 continue;
2515 default:
2516 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2517 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002518 }
2519 }
2520 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002521
Mark Whitley94fd4802001-03-12 23:08:34 +00002522 m->name = mn;
2523 m->addr = info.addr;
2524 m->nsyms = nsyms;
2525 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002526
Mark Whitley94fd4802001-03-12 23:08:34 +00002527 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2528 s->name += (unsigned long) syms;
2529 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002530 }
2531 }
2532
2533 /* Collect the kernel's symbols. */
2534
2535 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002536retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002537 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002538 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002539 syms = xrealloc(syms, bufsize = ret);
2540 goto retry_kern_sym_load;
2541 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002542 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002543 return 0;
2544 }
2545 nksyms = nsyms = ret;
2546 ksyms = syms;
2547
2548 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2549 s->name += (unsigned long) syms;
2550 }
2551 return 1;
2552}
2553
2554
2555/* Return the kernel symbol checksum version, or zero if not used. */
2556
2557static int new_is_kernel_checksummed(void)
2558{
2559 struct new_module_symbol *s;
2560 size_t i;
2561
2562 /* Using_Versions is not the first symbol, but it should be in there. */
2563
2564 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2565 if (strcmp((char *) s->name, "Using_Versions") == 0)
2566 return s->value;
2567
2568 return 0;
2569}
2570
2571
2572static int new_create_this_module(struct obj_file *f, const char *m_name)
2573{
2574 struct obj_section *sec;
2575
2576 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002577 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002578 memset(sec->contents, 0, sizeof(struct new_module));
2579
Miles Baderae28b042002-04-01 09:34:25 +00002580 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002581 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002582 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002583
2584 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002585 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002586
2587 return 1;
2588}
2589
Eric Andersen889dd202003-01-23 04:48:34 +00002590#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2591/* add an entry to the __ksymtab section, creating it if necessary */
2592static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2593{
2594 struct obj_section *sec;
2595 ElfW(Addr) ofs;
2596
2597 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2598 * If __ksymtab is defined but not marked alloc, x out the first character
2599 * (no obj_delete routine) and create a new __ksymtab with the correct
2600 * characteristics.
2601 */
2602 sec = obj_find_section(f, "__ksymtab");
2603 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2604 *((char *)(sec->name)) = 'x'; /* override const */
2605 sec = NULL;
2606 }
2607 if (!sec)
2608 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002609 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002610 if (!sec)
2611 return;
2612 sec->header.sh_flags |= SHF_ALLOC;
2613 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002614 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002615 ofs = sec->header.sh_size;
2616 obj_symbol_patch(f, sec->idx, ofs, sym);
2617 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2618 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2619}
2620#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002621
2622static int new_create_module_ksymtab(struct obj_file *f)
2623{
2624 struct obj_section *sec;
2625 int i;
2626
2627 /* We must always add the module references. */
2628
2629 if (n_ext_modules_used) {
2630 struct new_module_ref *dep;
2631 struct obj_symbol *tm;
2632
2633 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002634 (sizeof(struct new_module_ref)
2635 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002636 if (!sec)
2637 return 0;
2638
Miles Baderae28b042002-04-01 09:34:25 +00002639 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002640 dep = (struct new_module_ref *) sec->contents;
2641 for (i = 0; i < n_ext_modules; ++i)
2642 if (ext_modules[i].used) {
2643 dep->dep = ext_modules[i].addr;
2644 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002645 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002646 dep->next_ref = 0;
2647 ++dep;
2648 }
2649 }
2650
2651 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2652 size_t nsyms;
2653 int *loaded;
2654
2655 sec =
2656 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002657 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002658
2659 /* We don't want to export symbols residing in sections that
2660 aren't loaded. There are a number of these created so that
2661 we make sure certain module options don't appear twice. */
2662
2663 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2664 while (--i >= 0)
2665 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2666
2667 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2668 struct obj_symbol *sym;
2669 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002670 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002671 && sym->secidx <= SHN_HIRESERVE
2672 && (sym->secidx >= SHN_LORESERVE
2673 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002674 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2675
2676 obj_symbol_patch(f, sec->idx, ofs, sym);
2677 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002678 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002679
2680 nsyms++;
2681 }
2682 }
2683
2684 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2685 }
2686
2687 return 1;
2688}
2689
2690
2691static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002692new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002693{
2694 struct new_module *module;
2695 struct obj_section *sec;
2696 void *image;
2697 int ret;
2698 tgt_long m_addr;
2699
2700 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002701 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002702 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002703 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002704 module = (struct new_module *) sec->contents;
2705 m_addr = sec->header.sh_addr;
2706
2707 module->size_of_struct = sizeof(*module);
2708 module->size = m_size;
2709 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2710
2711 sec = obj_find_section(f, "__ksymtab");
2712 if (sec && sec->header.sh_size) {
2713 module->syms = sec->header.sh_addr;
2714 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2715 }
2716
2717 if (n_ext_modules_used) {
2718 sec = obj_find_section(f, ".kmodtab");
2719 module->deps = sec->header.sh_addr;
2720 module->ndeps = n_ext_modules_used;
2721 }
2722
2723 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002724 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002725 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002726 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002727
2728 sec = obj_find_section(f, "__ex_table");
2729 if (sec) {
2730 module->ex_table_start = sec->header.sh_addr;
2731 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2732 }
2733
2734 sec = obj_find_section(f, ".text.init");
2735 if (sec) {
2736 module->runsize = sec->header.sh_addr - m_addr;
2737 }
2738 sec = obj_find_section(f, ".data.init");
2739 if (sec) {
2740 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002741 module->runsize > sec->header.sh_addr - m_addr)
2742 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002743 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002744 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2745 if (sec && sec->header.sh_size) {
2746 module->archdata_start = (void*)sec->header.sh_addr;
2747 module->archdata_end = module->archdata_start + sec->header.sh_size;
2748 }
2749 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2750 if (sec && sec->header.sh_size) {
2751 module->kallsyms_start = (void*)sec->header.sh_addr;
2752 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2753 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002754
Eric Andersen9f16d612000-06-12 23:11:16 +00002755 /* Whew! All of the initialization is complete. Collect the final
2756 module image and give it to the kernel. */
2757
2758 image = xmalloc(m_size);
2759 obj_create_image(f, image);
2760
Eric Andersencb3b9b12004-06-22 11:50:52 +00002761 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002762 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002763 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002764
2765 free(image);
2766
2767 return ret == 0;
2768}
2769
Eric Andersen9f16d612000-06-12 23:11:16 +00002770
2771/*======================================================================*/
2772
Eric Andersen044228d2001-07-17 01:12:36 +00002773static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002774obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2775 const char *string)
2776{
2777 struct obj_string_patch *p;
2778 struct obj_section *strsec;
2779 size_t len = strlen(string) + 1;
2780 char *loc;
2781
2782 p = xmalloc(sizeof(*p));
2783 p->next = f->string_patches;
2784 p->reloc_secidx = secidx;
2785 p->reloc_offset = offset;
2786 f->string_patches = p;
2787
2788 strsec = obj_find_section(f, ".kstrtab");
2789 if (strsec == NULL) {
2790 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2791 p->string_offset = 0;
2792 loc = strsec->contents;
2793 } else {
2794 p->string_offset = strsec->header.sh_size;
2795 loc = obj_extend_section(strsec, len);
2796 }
2797 memcpy(loc, string, len);
2798
2799 return 1;
2800}
2801
Eric Andersen044228d2001-07-17 01:12:36 +00002802static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002803obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2804 struct obj_symbol *sym)
2805{
2806 struct obj_symbol_patch *p;
2807
2808 p = xmalloc(sizeof(*p));
2809 p->next = f->symbol_patches;
2810 p->reloc_secidx = secidx;
2811 p->reloc_offset = offset;
2812 p->sym = sym;
2813 f->symbol_patches = p;
2814
2815 return 1;
2816}
2817
Eric Andersen044228d2001-07-17 01:12:36 +00002818static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002819{
2820 unsigned long i;
2821 int ret = 1;
2822
2823 for (i = 0; i < HASH_BUCKETS; ++i) {
2824 struct obj_symbol *sym;
2825 for (sym = f->symtab[i]; sym; sym = sym->next)
2826 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002827 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002828 sym->secidx = SHN_ABS;
2829 sym->value = 0;
2830 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002831 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002832 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00002833 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002834 ret = 0;
2835 }
2836 }
2837 }
2838
2839 return ret;
2840}
2841
Eric Andersen044228d2001-07-17 01:12:36 +00002842static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002843{
2844 struct common_entry {
2845 struct common_entry *next;
2846 struct obj_symbol *sym;
2847 } *common_head = NULL;
2848
2849 unsigned long i;
2850
2851 for (i = 0; i < HASH_BUCKETS; ++i) {
2852 struct obj_symbol *sym;
2853 for (sym = f->symtab[i]; sym; sym = sym->next)
2854 if (sym->secidx == SHN_COMMON) {
2855 /* Collect all COMMON symbols and sort them by size so as to
2856 minimize space wasted by alignment requirements. */
2857 {
2858 struct common_entry **p, *n;
2859 for (p = &common_head; *p; p = &(*p)->next)
2860 if (sym->size <= (*p)->sym->size)
2861 break;
2862
2863 n = alloca(sizeof(*n));
2864 n->next = *p;
2865 n->sym = sym;
2866 *p = n;
2867 }
2868 }
2869 }
2870
2871 for (i = 1; i < f->local_symtab_size; ++i) {
2872 struct obj_symbol *sym = f->local_symtab[i];
2873 if (sym && sym->secidx == SHN_COMMON) {
2874 struct common_entry **p, *n;
2875 for (p = &common_head; *p; p = &(*p)->next)
2876 if (sym == (*p)->sym)
2877 break;
2878 else if (sym->size < (*p)->sym->size) {
2879 n = alloca(sizeof(*n));
2880 n->next = *p;
2881 n->sym = sym;
2882 *p = n;
2883 break;
2884 }
2885 }
2886 }
2887
2888 if (common_head) {
2889 /* Find the bss section. */
2890 for (i = 0; i < f->header.e_shnum; ++i)
2891 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2892 break;
2893
2894 /* If for some reason there hadn't been one, create one. */
2895 if (i == f->header.e_shnum) {
2896 struct obj_section *sec;
2897
2898 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2899 f->sections[i] = sec = arch_new_section();
2900 f->header.e_shnum = i + 1;
2901
2902 memset(sec, 0, sizeof(*sec));
2903 sec->header.sh_type = SHT_PROGBITS;
2904 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2905 sec->name = ".bss";
2906 sec->idx = i;
2907 }
2908
2909 /* Allocate the COMMONS. */
2910 {
2911 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2912 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2913 struct common_entry *c;
2914
2915 for (c = common_head; c; c = c->next) {
2916 ElfW(Addr) align = c->sym->value;
2917
2918 if (align > max_align)
2919 max_align = align;
2920 if (bss_size & (align - 1))
2921 bss_size = (bss_size | (align - 1)) + 1;
2922
2923 c->sym->secidx = i;
2924 c->sym->value = bss_size;
2925
2926 bss_size += c->sym->size;
2927 }
2928
2929 f->sections[i]->header.sh_size = bss_size;
2930 f->sections[i]->header.sh_addralign = max_align;
2931 }
2932 }
2933
2934 /* For the sake of patch relocation and parameter initialization,
2935 allocate zeroed data for NOBITS sections now. Note that after
2936 this we cannot assume NOBITS are really empty. */
2937 for (i = 0; i < f->header.e_shnum; ++i) {
2938 struct obj_section *s = f->sections[i];
2939 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002940 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002941 s->contents = memset(xmalloc(s->header.sh_size),
2942 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002943 else
2944 s->contents = NULL;
2945
Eric Andersen9f16d612000-06-12 23:11:16 +00002946 s->header.sh_type = SHT_PROGBITS;
2947 }
2948 }
2949}
2950
Eric Andersen044228d2001-07-17 01:12:36 +00002951static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002952{
2953 unsigned long dot = 0;
2954 struct obj_section *sec;
2955
2956 /* Finalize the positions of the sections relative to one another. */
2957
2958 for (sec = f->load_order; sec; sec = sec->load_next) {
2959 ElfW(Addr) align;
2960
2961 align = sec->header.sh_addralign;
2962 if (align && (dot & (align - 1)))
2963 dot = (dot | (align - 1)) + 1;
2964
2965 sec->header.sh_addr = dot;
2966 dot += sec->header.sh_size;
2967 }
2968
2969 return dot;
2970}
2971
Eric Andersen044228d2001-07-17 01:12:36 +00002972static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002973{
2974 int i, n = f->header.e_shnum;
2975 int ret = 1;
2976
2977 /* Finalize the addresses of the sections. */
2978
2979 f->baseaddr = base;
2980 for (i = 0; i < n; ++i)
2981 f->sections[i]->header.sh_addr += base;
2982
2983 /* And iterate over all of the relocations. */
2984
2985 for (i = 0; i < n; ++i) {
2986 struct obj_section *relsec, *symsec, *targsec, *strsec;
2987 ElfW(RelM) * rel, *relend;
2988 ElfW(Sym) * symtab;
2989 const char *strtab;
2990
2991 relsec = f->sections[i];
2992 if (relsec->header.sh_type != SHT_RELM)
2993 continue;
2994
2995 symsec = f->sections[relsec->header.sh_link];
2996 targsec = f->sections[relsec->header.sh_info];
2997 strsec = f->sections[symsec->header.sh_link];
2998
2999 rel = (ElfW(RelM) *) relsec->contents;
3000 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3001 symtab = (ElfW(Sym) *) symsec->contents;
3002 strtab = (const char *) strsec->contents;
3003
3004 for (; rel < relend; ++rel) {
3005 ElfW(Addr) value = 0;
3006 struct obj_symbol *intsym = NULL;
3007 unsigned long symndx;
3008 ElfW(Sym) * extsym = 0;
3009 const char *errmsg;
3010
3011 /* Attempt to find a value to use for this relocation. */
3012
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003013 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003014 if (symndx) {
3015 /* Note we've already checked for undefined symbols. */
3016
3017 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003018 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003019 /* Local symbols we look up in the local table to be sure
3020 we get the one that is really intended. */
3021 intsym = f->local_symtab[symndx];
3022 } else {
3023 /* Others we look up in the hash table. */
3024 const char *name;
3025 if (extsym->st_name)
3026 name = strtab + extsym->st_name;
3027 else
3028 name = f->sections[extsym->st_shndx]->name;
3029 intsym = obj_find_symbol(f, name);
3030 }
3031
3032 value = obj_symbol_final_value(f, intsym);
3033 intsym->referenced = 1;
3034 }
3035#if SHT_RELM == SHT_RELA
3036#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3037 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3038 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003039 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003040#endif
3041 value += rel->r_addend;
3042#endif
3043
3044 /* Do it! */
3045 switch (arch_apply_relocation
3046 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003047 case obj_reloc_ok:
3048 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003049
Eric Andersen3b1a7442003-12-24 20:30:45 +00003050 case obj_reloc_overflow:
3051 errmsg = "Relocation overflow";
3052 goto bad_reloc;
3053 case obj_reloc_dangerous:
3054 errmsg = "Dangerous relocation";
3055 goto bad_reloc;
3056 case obj_reloc_unhandled:
3057 errmsg = "Unhandled relocation";
3058bad_reloc:
3059 if (extsym) {
3060 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003061 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003062 strtab + extsym->st_name);
3063 } else {
3064 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003065 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003066 }
3067 ret = 0;
3068 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003069 }
3070 }
3071 }
3072
3073 /* Finally, take care of the patches. */
3074
3075 if (f->string_patches) {
3076 struct obj_string_patch *p;
3077 struct obj_section *strsec;
3078 ElfW(Addr) strsec_base;
3079 strsec = obj_find_section(f, ".kstrtab");
3080 strsec_base = strsec->header.sh_addr;
3081
3082 for (p = f->string_patches; p; p = p->next) {
3083 struct obj_section *targsec = f->sections[p->reloc_secidx];
3084 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3085 = strsec_base + p->string_offset;
3086 }
3087 }
3088
3089 if (f->symbol_patches) {
3090 struct obj_symbol_patch *p;
3091
3092 for (p = f->symbol_patches; p; p = p->next) {
3093 struct obj_section *targsec = f->sections[p->reloc_secidx];
3094 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3095 = obj_symbol_final_value(f, p->sym);
3096 }
3097 }
3098
3099 return ret;
3100}
3101
Eric Andersen044228d2001-07-17 01:12:36 +00003102static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003103{
3104 struct obj_section *sec;
3105 ElfW(Addr) base = f->baseaddr;
3106
3107 for (sec = f->load_order; sec; sec = sec->load_next) {
3108 char *secimg;
3109
Eric Andersen2bf658d2001-02-24 20:01:53 +00003110 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003111 continue;
3112
3113 secimg = image + (sec->header.sh_addr - base);
3114
3115 /* Note that we allocated data for NOBITS sections earlier. */
3116 memcpy(secimg, sec->contents, sec->header.sh_size);
3117 }
3118
3119 return 1;
3120}
3121
3122/*======================================================================*/
3123
Eric Andersen044228d2001-07-17 01:12:36 +00003124static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003125{
3126 struct obj_file *f;
3127 ElfW(Shdr) * section_headers;
3128 int shnum, i;
3129 char *shstrtab;
3130
3131 /* Read the file header. */
3132
3133 f = arch_new_file();
3134 memset(f, 0, sizeof(*f));
3135 f->symbol_cmp = strcmp;
3136 f->symbol_hash = obj_elf_hash;
3137 f->load_order_search_start = &f->load_order;
3138
3139 fseek(fp, 0, SEEK_SET);
3140 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003141 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003142 return NULL;
3143 }
3144
3145 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003146 || f->header.e_ident[EI_MAG1] != ELFMAG1
3147 || f->header.e_ident[EI_MAG2] != ELFMAG2
3148 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003149 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003150 return NULL;
3151 }
3152 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003153 || f->header.e_ident[EI_DATA] != ELFDATAM
3154 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3155 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003156 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003157 return NULL;
3158 }
3159 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003160 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003161 return NULL;
3162 }
3163
3164 /* Read the section headers. */
3165
3166 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003167 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003168 (unsigned long) f->header.e_shentsize,
3169 (unsigned long) sizeof(ElfW(Shdr)));
3170 return NULL;
3171 }
3172
3173 shnum = f->header.e_shnum;
3174 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3175 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3176
3177 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3178 fseek(fp, f->header.e_shoff, SEEK_SET);
3179 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003180 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003181 return NULL;
3182 }
3183
3184 /* Read the section data. */
3185
3186 for (i = 0; i < shnum; ++i) {
3187 struct obj_section *sec;
3188
3189 f->sections[i] = sec = arch_new_section();
3190 memset(sec, 0, sizeof(*sec));
3191
3192 sec->header = section_headers[i];
3193 sec->idx = i;
3194
Eric Andersen2bf658d2001-02-24 20:01:53 +00003195 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003196 case SHT_NULL:
3197 case SHT_NOTE:
3198 case SHT_NOBITS:
3199 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003200 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003201
3202 case SHT_PROGBITS:
3203#if LOADBITS
3204 if (!loadprogbits) {
3205 sec->contents = NULL;
3206 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003207 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003208#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003209 case SHT_SYMTAB:
3210 case SHT_STRTAB:
3211 case SHT_RELM:
3212 if (sec->header.sh_size > 0) {
3213 sec->contents = xmalloc(sec->header.sh_size);
3214 fseek(fp, sec->header.sh_offset, SEEK_SET);
3215 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3216 bb_perror_msg("error reading ELF section data");
3217 return NULL;
3218 }
3219 } else {
3220 sec->contents = NULL;
3221 }
3222 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003223
3224#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003225 case SHT_RELA:
3226 bb_error_msg("RELA relocations not supported on this architecture");
3227 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003228#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003229 case SHT_REL:
3230 bb_error_msg("REL relocations not supported on this architecture");
3231 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003232#endif
3233
Eric Andersen3b1a7442003-12-24 20:30:45 +00003234 default:
3235 if (sec->header.sh_type >= SHT_LOPROC) {
3236 /* Assume processor specific section types are debug
3237 info and can safely be ignored. If this is ever not
3238 the case (Hello MIPS?), don't put ifdefs here but
3239 create an arch_load_proc_section(). */
3240 break;
3241 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003242
Eric Andersen3b1a7442003-12-24 20:30:45 +00003243 bb_error_msg("can't handle sections of type %ld",
3244 (long) sec->header.sh_type);
3245 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003246 }
3247 }
3248
3249 /* Do what sort of interpretation as needed by each section. */
3250
3251 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3252
3253 for (i = 0; i < shnum; ++i) {
3254 struct obj_section *sec = f->sections[i];
3255 sec->name = shstrtab + sec->header.sh_name;
3256 }
3257
3258 for (i = 0; i < shnum; ++i) {
3259 struct obj_section *sec = f->sections[i];
3260
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003261 /* .modinfo should be contents only but gcc has no attribute for that.
3262 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3263 */
3264 if (strcmp(sec->name, ".modinfo") == 0)
3265 sec->header.sh_flags &= ~SHF_ALLOC;
3266
Eric Andersen9f16d612000-06-12 23:11:16 +00003267 if (sec->header.sh_flags & SHF_ALLOC)
3268 obj_insert_section_load_order(f, sec);
3269
3270 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003271 case SHT_SYMTAB:
3272 {
3273 unsigned long nsym, j;
3274 char *strtab;
3275 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003276
Eric Andersen3b1a7442003-12-24 20:30:45 +00003277 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3278 bb_error_msg("symbol size mismatch: %lu != %lu",
3279 (unsigned long) sec->header.sh_entsize,
3280 (unsigned long) sizeof(ElfW(Sym)));
3281 return NULL;
3282 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003283
Eric Andersen3b1a7442003-12-24 20:30:45 +00003284 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3285 strtab = f->sections[sec->header.sh_link]->contents;
3286 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003287
Eric Andersen3b1a7442003-12-24 20:30:45 +00003288 /* Allocate space for a table of local symbols. */
3289 j = f->local_symtab_size = sec->header.sh_info;
3290 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003291
Eric Andersen3b1a7442003-12-24 20:30:45 +00003292 /* Insert all symbols into the hash table. */
3293 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3294 ElfW(Addr) val = sym->st_value;
3295 const char *name;
3296 if (sym->st_name)
3297 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003298 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003299 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003300 else
3301 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003302
Eric Andersenbf833552003-08-13 19:56:33 +00003303#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003304 /*
3305 * For sh64 it is possible that the target of a branch
3306 * requires a mode switch (32 to 16 and back again).
3307 *
3308 * This is implied by the lsb being set in the target
3309 * address for SHmedia mode and clear for SHcompact.
3310 */
3311 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003312#endif
3313
Eric Andersen3b1a7442003-12-24 20:30:45 +00003314 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3315 val, sym->st_size);
3316 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003317 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003318 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003319
Eric Andersen3b1a7442003-12-24 20:30:45 +00003320 case SHT_RELM:
3321 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3322 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3323 (unsigned long) sec->header.sh_entsize,
3324 (unsigned long) sizeof(ElfW(RelM)));
3325 return NULL;
3326 }
3327 break;
3328 /* XXX Relocation code from modutils-2.3.19 is not here.
3329 * Why? That's about 20 lines of code from obj/obj_load.c,
3330 * which gets done in a second pass through the sections.
3331 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003332 }
3333 }
3334
3335 return f;
3336}
3337
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003338#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003339/*
3340 * load the unloaded sections directly into the memory allocated by
3341 * kernel for the module
3342 */
3343
Eric Andersenac5dbd12001-08-22 05:26:08 +00003344static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003345{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003346 ElfW(Addr) base = f->baseaddr;
3347 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003348
Eric Andersen8ae319a2001-05-21 16:09:18 +00003349 for (sec = f->load_order; sec; sec = sec->load_next) {
3350
3351 /* section already loaded? */
3352 if (sec->contents != NULL)
3353 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003354
Eric Andersen8ae319a2001-05-21 16:09:18 +00003355 if (sec->header.sh_size == 0)
3356 continue;
3357
3358 sec->contents = imagebase + (sec->header.sh_addr - base);
3359 fseek(fp, sec->header.sh_offset, SEEK_SET);
3360 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003361 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003362 return 0;
3363 }
3364
3365 }
3366 return 1;
3367}
3368#endif
3369
Eric Andersen9f16d612000-06-12 23:11:16 +00003370static void hide_special_symbols(struct obj_file *f)
3371{
3372 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003373 SPFX "cleanup_module",
3374 SPFX "init_module",
3375 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003376 NULL
3377 };
3378
3379 struct obj_symbol *sym;
3380 const char *const *p;
3381
3382 for (p = specials; *p; ++p)
3383 if ((sym = obj_find_symbol(f, *p)) != NULL)
3384 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003385 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003386}
3387
Glenn L McGrath759515c2003-08-30 06:00:33 +00003388
Eric Andersen71ae64b2002-10-10 04:20:21 +00003389#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003390static int obj_gpl_license(struct obj_file *f, const char **license)
3391{
3392 struct obj_section *sec;
3393 /* This list must match *exactly* the list of allowable licenses in
3394 * linux/include/linux/module.h. Checking for leading "GPL" will not
3395 * work, somebody will use "GPL sucks, this is proprietary".
3396 */
3397 static const char *gpl_licenses[] = {
3398 "GPL",
3399 "GPL v2",
3400 "GPL and additional rights",
3401 "Dual BSD/GPL",
3402 "Dual MPL/GPL",
3403 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003404
Eric Andersen166fa462002-09-16 05:30:24 +00003405 if ((sec = obj_find_section(f, ".modinfo"))) {
3406 const char *value, *ptr, *endptr;
3407 ptr = sec->contents;
3408 endptr = ptr + sec->header.sh_size;
3409 while (ptr < endptr) {
3410 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3411 int i;
3412 if (license)
3413 *license = value+1;
3414 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3415 if (strcmp(value+1, gpl_licenses[i]) == 0)
3416 return(0);
3417 }
3418 return(2);
3419 }
3420 if (strchr(ptr, '\0'))
3421 ptr = strchr(ptr, '\0') + 1;
3422 else
3423 ptr = endptr;
3424 }
3425 }
3426 return(1);
3427}
3428
3429#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3430#define TAINT_PROPRIETORY_MODULE (1<<0)
3431#define TAINT_FORCED_MODULE (1<<1)
3432#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003433#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003434
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003435static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003436 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3437{
3438 char buf[80];
3439 int oldval;
3440 static int first = 1;
3441 if (fd < 0 && !kernel_has_tainted)
3442 return; /* New modutils on old kernel */
3443 printf("Warning: loading %s will taint the kernel: %s%s\n",
3444 m_name, text1, text2);
3445 if (first) {
3446 printf(" See %s for information about tainted modules\n", TAINT_URL);
3447 first = 0;
3448 }
3449 if (fd >= 0) {
3450 read(fd, buf, sizeof(buf)-1);
3451 buf[sizeof(buf)-1] = '\0';
3452 oldval = strtoul(buf, NULL, 10);
3453 sprintf(buf, "%d\n", oldval | taint);
3454 write(fd, buf, strlen(buf));
3455 }
3456}
3457
3458/* Check if loading this module will taint the kernel. */
3459static void check_tainted_module(struct obj_file *f, char *m_name)
3460{
3461 static const char tainted_file[] = TAINT_FILENAME;
3462 int fd, kernel_has_tainted;
3463 const char *ptr;
3464
3465 kernel_has_tainted = 1;
3466 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3467 if (errno == ENOENT)
3468 kernel_has_tainted = 0;
3469 else if (errno == EACCES)
3470 kernel_has_tainted = 1;
3471 else {
3472 perror(tainted_file);
3473 kernel_has_tainted = 0;
3474 }
3475 }
3476
3477 switch (obj_gpl_license(f, &ptr)) {
3478 case 0:
3479 break;
3480 case 1:
3481 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3482 break;
3483 case 2:
3484 /* The module has a non-GPL license so we pretend that the
3485 * kernel always has a taint flag to get a warning even on
3486 * kernels without the proc flag.
3487 */
3488 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3489 break;
3490 default:
3491 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3492 break;
3493 }
3494
3495 if (flag_force_load)
3496 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3497
3498 if (fd >= 0)
3499 close(fd);
3500}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003501#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3502#define check_tainted_module(x, y) do { } while(0);
3503#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003504
Eric Andersen889dd202003-01-23 04:48:34 +00003505#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3506/* add module source, timestamp, kernel version and a symbol for the
3507 * start of some sections. this info is used by ksymoops to do better
3508 * debugging.
3509 */
3510static int
3511get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3512{
3513#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003514 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003515#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003516 strncpy(str, "???", sizeof(str));
3517 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003518#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3519}
3520
3521/* add module source, timestamp, kernel version and a symbol for the
3522 * start of some sections. this info is used by ksymoops to do better
3523 * debugging.
3524 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003525static void
Eric Andersen889dd202003-01-23 04:48:34 +00003526add_ksymoops_symbols(struct obj_file *f, const char *filename,
3527 const char *m_name)
3528{
3529 static const char symprefix[] = "__insmod_";
3530 struct obj_section *sec;
3531 struct obj_symbol *sym;
3532 char *name, *absolute_filename;
3533 char str[STRVERSIONLEN], real[PATH_MAX];
3534 int i, l, lm_name, lfilename, use_ksymtab, version;
3535 struct stat statbuf;
3536
3537 static const char *section_names[] = {
3538 ".text",
3539 ".rodata",
3540 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003541 ".bss",
3542 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003543 };
3544
3545 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003546 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003547 }
3548 else {
3549 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003550 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003551 errno = save_errno;
3552 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003553 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003554 }
3555
3556 lm_name = strlen(m_name);
3557 lfilename = strlen(absolute_filename);
3558
3559 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3560 * are not to be exported. otherwise leave ksymtab alone for now, the
3561 * "export all symbols" compatibility code will export these symbols later.
3562 */
3563 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3564
3565 if ((sec = obj_find_section(f, ".this"))) {
3566 /* tag the module header with the object name, last modified
3567 * timestamp and module version. worst case for module version
3568 * is 0xffffff, decimal 16777215. putting all three fields in
3569 * one symbol is less readable but saves kernel space.
3570 */
3571 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003572 lm_name+ /* module name */
3573 2+ /* "_O" */
3574 lfilename+ /* object filename */
3575 2+ /* "_M" */
3576 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3577 2+ /* "_V" */
3578 8+ /* version in dec */
3579 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003580 name = xmalloc(l);
3581 if (stat(absolute_filename, &statbuf) != 0)
3582 statbuf.st_mtime = 0;
3583 version = get_module_version(f, str); /* -1 if not found */
3584 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003585 symprefix, m_name, absolute_filename,
3586 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3587 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003588 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003589 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003590 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003591 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003592 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003593 }
3594 free(absolute_filename);
3595#ifdef _NOT_SUPPORTED_
3596 /* record where the persistent data is going, same address as previous symbol */
3597
3598 if (f->persist) {
3599 l = sizeof(symprefix)+ /* "__insmod_" */
3600 lm_name+ /* module name */
3601 2+ /* "_P" */
3602 strlen(f->persist)+ /* data store */
3603 1; /* nul */
3604 name = xmalloc(l);
3605 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003606 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003607 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003608 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003609 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003610 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003611 }
3612#endif /* _NOT_SUPPORTED_ */
3613 /* tag the desired sections if size is non-zero */
3614
3615 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3616 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003617 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003618 l = sizeof(symprefix)+ /* "__insmod_" */
3619 lm_name+ /* module name */
3620 2+ /* "_S" */
3621 strlen(sec->name)+ /* section name */
3622 2+ /* "_L" */
3623 8+ /* length in dec */
3624 1; /* nul */
3625 name = xmalloc(l);
3626 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003627 symprefix, m_name, sec->name,
3628 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003629 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003630 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003631 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003632 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003633 }
3634 }
3635}
3636#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3637
Eric Andersenbe65c352003-01-23 04:57:35 +00003638#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3639static void print_load_map(struct obj_file *f)
3640{
3641 struct obj_symbol *sym;
3642 struct obj_symbol **all, **p;
3643 struct obj_section *sec;
3644 int i, nsyms, *loaded;
3645
3646 /* Report on the section layout. */
3647
3648 printf("Sections: Size %-*s Align\n",
3649 (int) (2 * sizeof(void *)), "Address");
3650
3651 for (sec = f->load_order; sec; sec = sec->load_next) {
3652 int a;
3653 unsigned long tmp;
3654
3655 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3656 tmp >>= 1;
3657 if (a == -1)
3658 a = 0;
3659
3660 printf("%-15s %08lx %0*lx 2**%d\n",
3661 sec->name,
3662 (long)sec->header.sh_size,
3663 (int) (2 * sizeof(void *)),
3664 (long)sec->header.sh_addr,
3665 a);
3666 }
3667#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3668 /* Quick reference which section indicies are loaded. */
3669
3670 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3671 while (--i >= 0)
3672 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3673
3674 /* Collect the symbols we'll be listing. */
3675
3676 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3677 for (sym = f->symtab[i]; sym; sym = sym->next)
3678 if (sym->secidx <= SHN_HIRESERVE
3679 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3680 ++nsyms;
3681
3682 all = alloca(nsyms * sizeof(struct obj_symbol *));
3683
3684 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3685 for (sym = f->symtab[i]; sym; sym = sym->next)
3686 if (sym->secidx <= SHN_HIRESERVE
3687 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3688 *p++ = sym;
3689
3690 /* And list them. */
3691 printf("\nSymbols:\n");
3692 for (p = all; p < all + nsyms; ++p) {
3693 char type = '?';
3694 unsigned long value;
3695
3696 sym = *p;
3697 if (sym->secidx == SHN_ABS) {
3698 type = 'A';
3699 value = sym->value;
3700 } else if (sym->secidx == SHN_UNDEF) {
3701 type = 'U';
3702 value = 0;
3703 } else {
3704 sec = f->sections[sym->secidx];
3705
3706 if (sec->header.sh_type == SHT_NOBITS)
3707 type = 'B';
3708 else if (sec->header.sh_flags & SHF_ALLOC) {
3709 if (sec->header.sh_flags & SHF_EXECINSTR)
3710 type = 'T';
3711 else if (sec->header.sh_flags & SHF_WRITE)
3712 type = 'D';
3713 else
3714 type = 'R';
3715 }
3716 value = sym->value + sec->header.sh_addr;
3717 }
3718
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003719 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003720 type = tolower(type);
3721
3722 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3723 type, sym->name);
3724 }
3725#endif
3726}
3727
3728#endif
3729
Eric Andersen9f16d612000-06-12 23:11:16 +00003730extern int insmod_main( int argc, char **argv)
3731{
Eric Andersena18aaf12001-01-24 19:07:09 +00003732 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003733 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003734 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003735 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003736 unsigned long m_size;
3737 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003738 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003739 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003740 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003741 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003742 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003743#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003744 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003745 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003746 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003747#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003748#ifdef CONFIG_FEATURE_CLEAN_UP
3749 FILE *fp = 0;
3750#else
3751 FILE *fp;
3752#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003753#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3754 int flag_print_load_map = 0;
3755#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003756 int k_version = 0;
3757 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003758
Erik Andersene49d5ec2000-02-08 19:58:47 +00003759 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003760#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003761 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003762#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003763 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003764#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003765 {
3766 switch (opt) {
3767 case 'f': /* force loading */
3768 flag_force_load = 1;
3769 break;
3770 case 'k': /* module loaded by kerneld, auto-cleanable */
3771 flag_autoclean = 1;
3772 break;
3773 case 's': /* log to syslog */
3774 /* log to syslog -- not supported */
3775 /* but kernel needs this for request_module(), */
3776 /* as this calls: modprobe -k -s -- <module> */
3777 /* so silently ignore this flag */
3778 break;
3779 case 'v': /* verbose output */
3780 flag_verbose = 1;
3781 break;
3782 case 'q': /* silent */
3783 flag_quiet = 1;
3784 break;
3785 case 'x': /* do not export externs */
3786 flag_export = 0;
3787 break;
3788 case 'o': /* name the output module */
3789 free(m_name);
3790 m_name = bb_xstrdup(optarg);
3791 break;
3792 case 'L': /* Stub warning */
3793 /* This is needed for compatibility with modprobe.
3794 * In theory, this does locking, but we don't do
3795 * that. So be careful and plan your life around not
3796 * loading the same module 50 times concurrently. */
3797 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003798#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003799 case 'm': /* print module load map */
3800 flag_print_load_map = 1;
3801 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003802#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003803 default:
3804 bb_show_usage();
3805 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003806 }
Eric Andersen03d80912003-12-19 21:04:19 +00003807
Eric Andersena18aaf12001-01-24 19:07:09 +00003808 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003809 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003810 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003811
Erik Andersene49d5ec2000-02-08 19:58:47 +00003812 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003813 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003814 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003815 len = strlen(tmp);
3816
Eric Andersen03d80912003-12-19 21:04:19 +00003817 if (uname(&myuname) == 0) {
3818 if (myuname.release[0] == '2') {
3819 k_version = myuname.release[2] - '0';
3820 }
3821 }
3822
3823#if defined(CONFIG_FEATURE_2_6_MODULES)
3824 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003825 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003826 len-=3;
3827 tmp[len] = '\0';
3828 }
3829 else
3830#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003831 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3832 len-=2;
3833 tmp[len] = '\0';
3834 }
Eric Andersen2d342152002-06-18 05:16:25 +00003835
Eric Andersen03d80912003-12-19 21:04:19 +00003836
3837#if defined(CONFIG_FEATURE_2_6_MODULES)
3838 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00003839 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003840 else
Eric Andersen03d80912003-12-19 21:04:19 +00003841#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00003842 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003843
Eric Andersen61f83052002-06-22 17:15:42 +00003844 if (!m_name) {
3845 m_name = tmp;
3846 } else {
3847 free(tmp1);
3848 tmp1 = 0; /* flag for free(m_name) before exit() */
3849 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003850
Eric Andersen14d35432001-05-14 17:07:32 +00003851 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003852 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3853 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003854 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3855 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003856 if (k_version) { /* uname succeedd */
3857 char *module_dir;
3858 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003859 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003860
Eric Andersen03d80912003-12-19 21:04:19 +00003861 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003862 /* Jump through hoops in case /lib/modules/`uname -r`
3863 * is a symlink. We do not want recursive_action to
3864 * follow symlinks, but we do want to follow the
3865 * /lib/modules/`uname -r` dir, So resolve it ourselves
3866 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00003867 if (realpath (tmdn, real_module_dir) == NULL)
3868 module_dir = tmdn;
3869 else
3870 module_dir = real_module_dir;
3871 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003872 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00003873 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00003874 }
3875
3876 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00003877 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003878 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003879 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003880
Eric Andersen03d80912003-12-19 21:04:19 +00003881 free(m_filename);
3882 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003883 if (realpath (_PATH_MODULES, module_dir) == NULL)
3884 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003885 /* No module found under /lib/modules/`uname -r`, this
3886 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00003887 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00003888 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00003889 {
Eric Andersen61f83052002-06-22 17:15:42 +00003890 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00003891 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00003892 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003893 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00003894 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00003895 }
3896 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003897 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00003898 }
Eric Andersen03d80912003-12-19 21:04:19 +00003899 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003900 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00003901
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00003902 if (!flag_quiet)
3903 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003904
Eric Andersene7047882003-12-11 01:42:13 +00003905#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003906 if (k_version > 4)
3907 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003908 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00003909 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003910 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00003911 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003912#endif
3913
Eric Andersen8ae319a2001-05-21 16:09:18 +00003914 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003915 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003916
Eric Andersen9f16d612000-06-12 23:11:16 +00003917 if (get_modinfo_value(f, "kernel_version") == NULL)
3918 m_has_modinfo = 0;
3919 else
3920 m_has_modinfo = 1;
3921
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003922#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003923 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00003924 if (!flag_quiet) {
3925 if (uname(&uts_info) < 0)
3926 uts_info.release[0] = '\0';
3927 if (m_has_modinfo) {
3928 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00003929 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003930 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00003931 "compiled for");
3932 goto out;
3933 }
3934 }
3935
3936 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
3937 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003938 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003939 "\t%s was compiled for kernel version %s\n"
3940 "\twhile this kernel is version %s",
3941 m_filename, m_strversion, uts_info.release);
3942 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003943 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003944 "\t%s was compiled for kernel version %s\n"
3945 "\twhile this kernel is version %s.",
3946 m_filename, m_strversion, uts_info.release);
3947 goto out;
3948 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003949 }
3950 }
3951 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003952#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003953
Eric Andersencb3b9b12004-06-22 11:50:52 +00003954 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003955 if (!new_get_kernel_symbols())
3956 goto out;
3957 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00003958 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003959 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003960 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00003961 }
3962
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003963#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003964 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00003965 if (m_has_modinfo)
3966 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003967
3968 if (m_crcs != k_crcs)
3969 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003970#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003971
Erik Andersene49d5ec2000-02-08 19:58:47 +00003972 /* Let the module know about the kernel symbols. */
3973 add_kernel_symbols(f);
3974
Eric Andersen9f16d612000-06-12 23:11:16 +00003975 /* Allocate common symbols, symbol tables, and string tables. */
3976
Eric Andersencb3b9b12004-06-22 11:50:52 +00003977 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003978 {
3979 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003980 }
3981
Eric Andersen9f16d612000-06-12 23:11:16 +00003982 if (!obj_check_undefineds(f)) {
3983 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003984 }
3985 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00003986 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003987
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003988 /* done with the module name, on to the optional var=value arguments */
3989 ++optind;
3990
Eric Andersen9f16d612000-06-12 23:11:16 +00003991 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00003992 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00003993 {
3994 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003995 }
3996 }
3997
Eric Andersen9f16d612000-06-12 23:11:16 +00003998 arch_create_got(f);
3999 hide_special_symbols(f);
4000
Eric Andersen889dd202003-01-23 04:48:34 +00004001#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4002 add_ksymoops_symbols(f, m_filename, m_name);
4003#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4004
Eric Andersencb3b9b12004-06-22 11:50:52 +00004005 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004006
Erik Andersene49d5ec2000-02-08 19:58:47 +00004007 /* Find current size of the module */
4008 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004009
4010
Erik Andersene49d5ec2000-02-08 19:58:47 +00004011 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004012 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004013 case EEXIST:
4014 bb_error_msg("A module named %s already exists", m_name);
4015 goto out;
4016 case ENOMEM:
4017 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4018 m_size);
4019 goto out;
4020 default:
4021 bb_perror_msg("create_module: %s", m_name);
4022 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004023 }
Erik Andersend387d011999-12-21 02:55:11 +00004024
Eric Andersen8ae319a2001-05-21 16:09:18 +00004025#if !LOADBITS
4026 /*
4027 * the PROGBITS section was not loaded by the obj_load
4028 * now we can load them directly into the kernel memory
4029 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004030 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004031 delete_module(m_name);
4032 goto out;
4033 }
Eric Andersen03d80912003-12-19 21:04:19 +00004034#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004035
Eric Andersen9f16d612000-06-12 23:11:16 +00004036 if (!obj_relocate(f, m_addr)) {
4037 delete_module(m_name);
4038 goto out;
4039 }
Erik Andersend387d011999-12-21 02:55:11 +00004040
Eric Andersencb3b9b12004-06-22 11:50:52 +00004041 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004042 {
4043 delete_module(m_name);
4044 goto out;
4045 }
4046
Eric Andersenbe65c352003-01-23 04:57:35 +00004047#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4048 if(flag_print_load_map)
4049 print_load_map(f);
4050#endif
4051
Matt Kraai3e856ce2000-12-01 02:55:13 +00004052 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004053
4054out:
Eric Andersen61f83052002-06-22 17:15:42 +00004055#ifdef CONFIG_FEATURE_CLEAN_UP
4056 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004057 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004058 if(tmp1) {
4059 free(tmp1);
4060 } else {
4061 free(m_name);
4062 }
4063 free(m_filename);
4064#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004065 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004066}
Eric Andersene7047882003-12-11 01:42:13 +00004067
4068
4069#endif
4070
4071
4072#ifdef CONFIG_FEATURE_2_6_MODULES
4073
4074#include <sys/mman.h>
4075#include <asm/unistd.h>
4076#include <sys/syscall.h>
4077
4078/* We use error numbers in a loose translation... */
4079static const char *moderror(int err)
4080{
4081 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004082 case ENOEXEC:
4083 return "Invalid module format";
4084 case ENOENT:
4085 return "Unknown symbol in module";
4086 case ESRCH:
4087 return "Module has wrong symbol version";
4088 case EINVAL:
4089 return "Invalid parameters";
4090 default:
4091 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004092 }
4093}
4094
4095extern int insmod_ng_main( int argc, char **argv)
4096{
4097 int i;
4098 int fd;
4099 long int ret;
4100 struct stat st;
4101 unsigned long len;
4102 void *map;
4103 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004104
Eric Andersene7047882003-12-11 01:42:13 +00004105 filename = argv[1];
4106 if (!filename) {
4107 bb_show_usage();
4108 return -1;
4109 }
4110
4111 /* Rest is options */
4112 for (i = 2; i < argc; i++) {
4113 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4114 /* Spaces handled by "" pairs, but no way of escaping quotes */
4115 if (strchr(argv[i], ' ')) {
4116 strcat(options, "\"");
4117 strcat(options, argv[i]);
4118 strcat(options, "\"");
4119 } else {
4120 strcat(options, argv[i]);
4121 }
4122 strcat(options, " ");
4123 }
4124
4125 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4126 bb_perror_msg_and_die("cannot open module `%s'", filename);
4127 }
4128
4129 fstat(fd, &st);
4130 len = st.st_size;
4131 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4132 if (map == MAP_FAILED) {
4133 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4134 }
4135
4136 ret = syscall(__NR_init_module, map, len, options);
4137 if (ret != 0) {
4138 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004139 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004140 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004141
Eric Andersene7047882003-12-11 01:42:13 +00004142 return 0;
4143}
4144
4145#endif