blob: 38bddbb6ff6ba36f01e72044d8c066666305a8c8 [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 */
113#if defined(__alpha__)
114#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 Frysinger63654c12004-12-26 09:13:32 +0000146/* PA-RISC / HP-PA */
147#if defined(__hppa__)
148#define MATCH_MACHINE(x) (x == EM_PARISC)
149#define SHT_RELM SHT_RELA
150#if defined(__LP64__)
151#define Elf64_RelM Elf64_Rela
152#define ELFCLASSM ELFCLASS64
153#else
154#define Elf32_RelM Elf32_Rela
155#define ELFCLASSM ELFCLASS32
156#endif
157#endif
158
Eric Andersen45a05132004-09-02 23:03:25 +0000159/* H8/300 */
160#if defined(__H8300H__) || defined(__H8300S__)
161#define MATCH_MACHINE(x) (x == EM_H8_300)
162#define SHT_RELM SHT_RELA
163#define Elf32_RelM Elf32_Rela
164#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000165#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000166#define SYMBOL_PREFIX "_"
167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
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
531struct obj_string_patch;
532struct obj_symbol_patch;
533
534struct obj_section
535{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000536 ElfW(Shdr) header;
537 const char *name;
538 char *contents;
539 struct obj_section *load_next;
540 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000541};
542
543struct obj_symbol
544{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000545 struct obj_symbol *next; /* hash table link */
546 const char *name;
547 unsigned long value;
548 unsigned long size;
549 int secidx; /* the defining section index/module */
550 int info;
551 int ksymidx; /* for export to the kernel symtab */
552 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000553};
554
555/* Hardcode the hash table size. We shouldn't be needing so many
556 symbols that we begin to degrade performance, and we get a big win
557 by giving the compiler a constant divisor. */
558
559#define HASH_BUCKETS 521
560
561struct obj_file
562{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000563 ElfW(Ehdr) header;
564 ElfW(Addr) baseaddr;
565 struct obj_section **sections;
566 struct obj_section *load_order;
567 struct obj_section **load_order_search_start;
568 struct obj_string_patch *string_patches;
569 struct obj_symbol_patch *symbol_patches;
570 int (*symbol_cmp)(const char *, const char *);
571 unsigned long (*symbol_hash)(const char *);
572 unsigned long local_symtab_size;
573 struct obj_symbol **local_symtab;
574 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000575};
576
577enum obj_reloc
578{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000579 obj_reloc_ok,
580 obj_reloc_overflow,
581 obj_reloc_dangerous,
582 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000583};
584
585struct obj_string_patch
586{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000587 struct obj_string_patch *next;
588 int reloc_secidx;
589 ElfW(Addr) reloc_offset;
590 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000591};
592
593struct obj_symbol_patch
594{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000595 struct obj_symbol_patch *next;
596 int reloc_secidx;
597 ElfW(Addr) reloc_offset;
598 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000599};
600
601
602/* Generic object manipulation routines. */
603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000605
Eric Andersen044228d2001-07-17 01:12:36 +0000606static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000607
Eric Andersen044228d2001-07-17 01:12:36 +0000608static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000609 const char *name);
610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000612 struct obj_symbol *sym);
613
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000614#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000615static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000616 int (*cmp)(const char *, const char *),
617 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000618#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000619
Eric Andersen044228d2001-07-17 01:12:36 +0000620static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000621 const char *name);
622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000624 struct obj_section *sec);
625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 const char *name,
628 unsigned long align,
629 unsigned long size);
630
Eric Andersen044228d2001-07-17 01:12:36 +0000631static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000632 const char *name,
633 unsigned long align,
634 unsigned long size);
635
Eric Andersen044228d2001-07-17 01:12:36 +0000636static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000637
Eric Andersen044228d2001-07-17 01:12:36 +0000638static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000639 const char *string);
640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000642 struct obj_symbol *sym);
643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000645
Eric Andersen044228d2001-07-17 01:12:36 +0000646static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000647
Eric Andersen044228d2001-07-17 01:12:36 +0000648static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000649
Eric Andersen044228d2001-07-17 01:12:36 +0000650static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Eric Andersen044228d2001-07-17 01:12:36 +0000652static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000653
Eric Andersen044228d2001-07-17 01:12:36 +0000654static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000655
656/* Architecture specific manipulation routines. */
657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen044228d2001-07-17 01:12:36 +0000662static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000663
Eric Andersen044228d2001-07-17 01:12:36 +0000664static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000665 struct obj_section *targsec,
666 struct obj_section *symsec,
667 struct obj_symbol *sym,
668 ElfW(RelM) *rel, ElfW(Addr) value);
669
Eric Andersencffd5022002-05-24 06:50:15 +0000670static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000671
Glenn L McGrath759515c2003-08-30 06:00:33 +0000672static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000673
Eric Andersen9f16d612000-06-12 23:11:16 +0000674#endif /* obj.h */
675//----------------------------------------------------------------------------
676//--------end of modutils obj.h
677//----------------------------------------------------------------------------
678
679
Miles Baderae28b042002-04-01 09:34:25 +0000680/* SPFX is always a string, so it can be concatenated to string constants. */
681#ifdef SYMBOL_PREFIX
682#define SPFX SYMBOL_PREFIX
683#else
684#define SPFX ""
685#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000686
Erik Andersen02104321999-12-17 18:57:34 +0000687
Erik Andersend387d011999-12-21 02:55:11 +0000688#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000689static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000690
Eric Andersen9f16d612000-06-12 23:11:16 +0000691/*======================================================================*/
692
Eric Andersen044228d2001-07-17 01:12:36 +0000693static int flag_force_load = 0;
694static int flag_autoclean = 0;
695static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000696static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000697static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000698
699
700/*======================================================================*/
701
Eric Andersencffd5022002-05-24 06:50:15 +0000702#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000703
Eric Andersencffd5022002-05-24 06:50:15 +0000704struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000705{
Eric Andersencffd5022002-05-24 06:50:15 +0000706 struct arch_list_entry *next;
707 CONFIG_LIST_ARCHTYPE addend;
708 int offset;
709 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000710};
Eric Andersencffd5022002-05-24 06:50:15 +0000711
Eric Andersen21adca72000-12-06 18:18:26 +0000712#endif
713
Eric Andersencffd5022002-05-24 06:50:15 +0000714#if defined(CONFIG_USE_SINGLE)
715
716struct arch_single_entry
717{
Eric Andersen9f16d612000-06-12 23:11:16 +0000718 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000719 int inited : 1;
720 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000721};
Eric Andersencffd5022002-05-24 06:50:15 +0000722
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000723#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000724
Eric Andersen2bf658d2001-02-24 20:01:53 +0000725#if defined(__mips__)
726struct mips_hi16
727{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000728 struct mips_hi16 *next;
729 Elf32_Addr *addr;
730 Elf32_Addr value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000731};
732#endif
733
Eric Andersenfe4208f2000-09-24 03:44:29 +0000734struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000735 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000736#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000737 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000738#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000739#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000740 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000741#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000742#if defined(__mips__)
743 struct mips_hi16 *mips_hi16_list;
744#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000745};
746
Eric Andersenfe4208f2000-09-24 03:44:29 +0000747struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000748 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000749#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000750#if defined(CONFIG_USE_PLT_LIST)
751 struct arch_list_entry *pltent;
752#else
753 struct arch_single_entry pltent;
754#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000755#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000756#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000757 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000758#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000759};
760
761
Eric Andersen9f16d612000-06-12 23:11:16 +0000762struct external_module {
763 const char *name;
764 ElfW(Addr) addr;
765 int used;
766 size_t nsyms;
767 struct new_module_symbol *syms;
768};
769
Eric Andersen044228d2001-07-17 01:12:36 +0000770static struct new_module_symbol *ksyms;
771static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000772
Eric Andersen044228d2001-07-17 01:12:36 +0000773static struct external_module *ext_modules;
774static int n_ext_modules;
775static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000776extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000777
Eric Andersen61f83052002-06-22 17:15:42 +0000778static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000779static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000780
Eric Andersenfe4208f2000-09-24 03:44:29 +0000781
Erik Andersen02104321999-12-17 18:57:34 +0000782
Eric Andersen9f16d612000-06-12 23:11:16 +0000783/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000784
Eric Andersen9f16d612000-06-12 23:11:16 +0000785
Eric Andersen14d35432001-05-14 17:07:32 +0000786static int check_module_name_match(const char *filename, struct stat *statbuf,
787 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000788{
Eric Andersen14d35432001-05-14 17:07:32 +0000789 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000790
Eric Andersen14d35432001-05-14 17:07:32 +0000791 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000792 return (FALSE);
793 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000794 char *tmp, *tmp1 = bb_xstrdup(filename);
795 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000796 if (strcmp(tmp, fullname) == 0) {
797 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000798 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000799 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000800 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000801 }
Eric Andersen14d35432001-05-14 17:07:32 +0000802 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000803 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000804 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000805}
806
Erik Andersen02104321999-12-17 18:57:34 +0000807
Eric Andersen9f16d612000-06-12 23:11:16 +0000808/*======================================================================*/
809
Eric Andersen044228d2001-07-17 01:12:36 +0000810static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000811{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000813 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000814
Eric Andersencffd5022002-05-24 06:50:15 +0000815 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816
Eric Andersen9f16d612000-06-12 23:11:16 +0000817 return &f->root;
818}
819
Eric Andersen044228d2001-07-17 01:12:36 +0000820static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000821{
822 return xmalloc(sizeof(struct obj_section));
823}
824
Eric Andersen044228d2001-07-17 01:12:36 +0000825static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000826{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000827 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000828 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000829
Eric Andersencffd5022002-05-24 06:50:15 +0000830 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 return &sym->root;
833}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000834
Eric Andersen044228d2001-07-17 01:12:36 +0000835static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000836arch_apply_relocation(struct obj_file *f,
837 struct obj_section *targsec,
838 struct obj_section *symsec,
839 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000840 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000841{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000842 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000843 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000844 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
845 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000846#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
847 struct arch_symbol *isym = (struct arch_symbol *) sym;
848#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000849#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000850 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000851#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000852#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000853 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000854 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000855#if defined(CONFIG_USE_PLT_LIST)
856 struct arch_list_entry *pe;
857#else
858 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000859#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000860#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000861
862 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000863
Eric Andersencffd5022002-05-24 06:50:15 +0000864#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000865 case R_ARM_NONE:
866 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000867
Eric Andersen3b1a7442003-12-24 20:30:45 +0000868 case R_ARM_ABS32:
869 *loc += v;
870 break;
Miles Baderae28b042002-04-01 09:34:25 +0000871
Eric Andersen3b1a7442003-12-24 20:30:45 +0000872 case R_ARM_GOT32:
873 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000874
Eric Andersen3b1a7442003-12-24 20:30:45 +0000875 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000876 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
877 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000879
Eric Andersen3b1a7442003-12-24 20:30:45 +0000880 assert(got);
881 *loc += got - dot;
882 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000883
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 case R_ARM_PC24:
885 case R_ARM_PLT32:
886 goto bb_use_plt;
887
888 case R_ARM_GOTOFF: /* address relative to the got */
889 assert(got);
890 *loc += v - got;
891 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000892
Eric Andersenbf77f612003-01-23 06:02:39 +0000893#elif defined(__s390__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 case R_390_32:
895 *(unsigned int *) loc += v;
896 break;
897 case R_390_16:
898 *(unsigned short *) loc += v;
899 break;
900 case R_390_8:
901 *(unsigned char *) loc += v;
902 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000903
Eric Andersen3b1a7442003-12-24 20:30:45 +0000904 case R_390_PC32:
905 *(unsigned int *) loc += v - dot;
906 break;
907 case R_390_PC16DBL:
908 *(unsigned short *) loc += (v - dot) >> 1;
909 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000910 case R_390_PC16:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000911 *(unsigned short *) loc += v - dot;
912 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000913
Eric Andersen3b1a7442003-12-24 20:30:45 +0000914 case R_390_PLT32:
915 case R_390_PLT16DBL:
916 /* find the plt entry and initialize it. */
917 assert(isym != NULL);
918 pe = (struct arch_single_entry *) &isym->pltent;
919 assert(pe->allocated);
920 if (pe->inited == 0) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000921 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000922 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
923 ip[1] = 0x100607f1;
924 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
925 ip[2] = v - 2;
926 else
927 ip[2] = v;
928 pe->inited = 1;
929 }
Eric Andersenbf77f612003-01-23 06:02:39 +0000930
Eric Andersen3b1a7442003-12-24 20:30:45 +0000931 /* Insert relative distance to target. */
932 v = plt + pe->offset - dot;
933 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
934 *(unsigned int *) loc = (unsigned int) v;
935 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
936 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
937 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000938
Eric Andersen3b1a7442003-12-24 20:30:45 +0000939 case R_390_GLOB_DAT:
940 case R_390_JMP_SLOT:
941 *loc = v;
942 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000943
Eric Andersen3b1a7442003-12-24 20:30:45 +0000944 case R_390_RELATIVE:
945 *loc += f->baseaddr;
946 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000947
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 case R_390_GOTPC:
949 assert(got != 0);
950 *(unsigned long *) loc += got - dot;
951 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000952
Eric Andersen3b1a7442003-12-24 20:30:45 +0000953 case R_390_GOT12:
954 case R_390_GOT16:
955 case R_390_GOT32:
956 assert(isym != NULL);
957 assert(got != 0);
958 if (!isym->gotent.inited)
959 {
960 isym->gotent.inited = 1;
961 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
962 }
963 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
964 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
965 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
966 *(unsigned short *) loc += isym->gotent.offset;
967 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
968 *(unsigned int *) loc += isym->gotent.offset;
969 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000970
Eric Andersen951df202003-10-21 06:45:29 +0000971#ifndef R_390_GOTOFF32
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000972#define R_390_GOTOFF32 R_390_GOTOFF
Eric Andersen951df202003-10-21 06:45:29 +0000973#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_390_GOTOFF32:
975 assert(got != 0);
976 *loc += v - got;
977 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000978
Eric Andersencffd5022002-05-24 06:50:15 +0000979#elif defined(__i386__)
980
Eric Andersen3b1a7442003-12-24 20:30:45 +0000981 case R_386_NONE:
982 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000983
Eric Andersen3b1a7442003-12-24 20:30:45 +0000984 case R_386_32:
985 *loc += v;
986 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000987
Eric Andersen3b1a7442003-12-24 20:30:45 +0000988 case R_386_PLT32:
989 case R_386_PC32:
990 *loc += v - dot;
991 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000992
Eric Andersen3b1a7442003-12-24 20:30:45 +0000993 case R_386_GLOB_DAT:
994 case R_386_JMP_SLOT:
995 *loc = v;
996 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000997
Eric Andersen3b1a7442003-12-24 20:30:45 +0000998 case R_386_RELATIVE:
999 *loc += f->baseaddr;
1000 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001001
Eric Andersen3b1a7442003-12-24 20:30:45 +00001002 case R_386_GOTPC:
1003 assert(got != 0);
1004 *loc += got - dot;
1005 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001006
Eric Andersen3b1a7442003-12-24 20:30:45 +00001007 case R_386_GOT32:
1008 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001009
Eric Andersen3b1a7442003-12-24 20:30:45 +00001010 case R_386_GOTOFF:
1011 assert(got != 0);
1012 *loc += v - got;
1013 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001014
Mike Frysinger91fbdac2005-10-02 06:44:39 +00001015#elif defined(__x86_64__)
1016
1017 case R_X86_64_NONE:
1018 break;
1019
1020 case R_X86_64_64:
1021 *loc += v;
1022 break;
1023
1024 case R_X86_64_32:
1025 *(unsigned int *) loc += v;
1026 if (v > 0xffffffff)
1027 {
1028 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1029 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1030 }
1031 break;
1032
1033 case R_X86_64_32S:
1034 *(signed int *) loc += v;
1035 break;
1036
1037 case R_X86_64_16:
1038 *(unsigned short *) loc += v;
1039 break;
1040
1041 case R_X86_64_8:
1042 *(unsigned char *) loc += v;
1043 break;
1044
1045 case R_X86_64_PC32:
1046 *(unsigned int *) loc += v - dot;
1047 break;
1048
1049 case R_X86_64_PC16:
1050 *(unsigned short *) loc += v - dot;
1051 break;
1052
1053 case R_X86_64_PC8:
1054 *(unsigned char *) loc += v - dot;
1055 break;
1056
1057 case R_X86_64_GLOB_DAT:
1058 case R_X86_64_JUMP_SLOT:
1059 *loc = v;
1060 break;
1061
1062 case R_X86_64_RELATIVE:
1063 *loc += f->baseaddr;
1064 break;
1065
1066 case R_X86_64_GOT32:
1067 case R_X86_64_GOTPCREL:
1068 goto bb_use_got;
1069#if 0
1070 assert(isym != NULL);
1071 if (!isym->gotent.reloc_done)
1072 {
1073 isym->gotent.reloc_done = 1;
1074 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1075 }
1076 /* XXX are these really correct? */
1077 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1078 *(unsigned int *) loc += v + isym->gotent.offset;
1079 else
1080 *loc += isym->gotent.offset;
1081 break;
1082#endif
1083
Eric Andersencffd5022002-05-24 06:50:15 +00001084#elif defined(__mc68000__)
1085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_68K_NONE:
1087 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001088
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089 case R_68K_32:
1090 *loc += v;
1091 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001092
Eric Andersen3b1a7442003-12-24 20:30:45 +00001093 case R_68K_8:
1094 if (v > 0xff) {
1095 ret = obj_reloc_overflow;
1096 }
1097 *(char *)loc = v;
1098 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001099
Eric Andersen3b1a7442003-12-24 20:30:45 +00001100 case R_68K_16:
1101 if (v > 0xffff) {
1102 ret = obj_reloc_overflow;
1103 }
1104 *(short *)loc = v;
1105 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001106
Eric Andersen3b1a7442003-12-24 20:30:45 +00001107 case R_68K_PC8:
1108 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001109 if ((Elf32_Sword)v > 0x7f ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001110 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1111 ret = obj_reloc_overflow;
1112 }
1113 *(char *)loc = v;
1114 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001115
Eric Andersen3b1a7442003-12-24 20:30:45 +00001116 case R_68K_PC16:
1117 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001118 if ((Elf32_Sword)v > 0x7fff ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001119 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1120 ret = obj_reloc_overflow;
1121 }
1122 *(short *)loc = v;
1123 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001124
Eric Andersen3b1a7442003-12-24 20:30:45 +00001125 case R_68K_PC32:
1126 *(int *)loc = v - dot;
1127 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001128
Eric Andersen3b1a7442003-12-24 20:30:45 +00001129 case R_68K_GLOB_DAT:
1130 case R_68K_JMP_SLOT:
1131 *loc = v;
1132 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001133
Eric Andersen3b1a7442003-12-24 20:30:45 +00001134 case R_68K_RELATIVE:
1135 *(int *)loc += f->baseaddr;
1136 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001137
Eric Andersen3b1a7442003-12-24 20:30:45 +00001138 case R_68K_GOT32:
1139 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001140
Eric Andersen16451a02004-03-19 12:16:18 +00001141#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001142 case R_68K_GOTOFF:
1143 assert(got != 0);
1144 *loc += v - got;
1145 break;
Eric Andersen16451a02004-03-19 12:16:18 +00001146#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001147
1148#elif defined(__mips__)
1149
Eric Andersen3b1a7442003-12-24 20:30:45 +00001150 case R_MIPS_NONE:
1151 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001152
Eric Andersen3b1a7442003-12-24 20:30:45 +00001153 case R_MIPS_32:
1154 *loc += v;
1155 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001156
Eric Andersen3b1a7442003-12-24 20:30:45 +00001157 case R_MIPS_26:
1158 if (v % 4)
1159 ret = obj_reloc_dangerous;
1160 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1161 ret = obj_reloc_overflow;
1162 *loc =
1163 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1164 0x03ffffff);
1165 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001166
Eric Andersen3b1a7442003-12-24 20:30:45 +00001167 case R_MIPS_HI16:
1168 {
1169 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001170
Eric Andersen3b1a7442003-12-24 20:30:45 +00001171 /* We cannot relocate this one now because we don't know the value
1172 of the carry we need to add. Save the information, and let LO16
1173 do the actual relocation. */
1174 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1175 n->addr = loc;
1176 n->value = v;
1177 n->next = ifile->mips_hi16_list;
1178 ifile->mips_hi16_list = n;
1179 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001180 }
1181
Eric Andersen3b1a7442003-12-24 20:30:45 +00001182 case R_MIPS_LO16:
1183 {
1184 unsigned long insnlo = *loc;
1185 Elf32_Addr val, vallo;
1186
1187 /* Sign extend the addend we extract from the lo insn. */
1188 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1189
1190 if (ifile->mips_hi16_list != NULL) {
1191 struct mips_hi16 *l;
1192
1193 l = ifile->mips_hi16_list;
1194 while (l != NULL) {
1195 struct mips_hi16 *next;
1196 unsigned long insn;
1197
1198 /* The value for the HI16 had best be the same. */
1199 assert(v == l->value);
1200
1201 /* Do the HI16 relocation. Note that we actually don't
1202 need to know anything about the LO16 itself, except where
1203 to find the low 16 bits of the addend needed by the LO16. */
1204 insn = *l->addr;
1205 val =
1206 ((insn & 0xffff) << 16) +
1207 vallo;
1208 val += v;
1209
1210 /* Account for the sign extension that will happen in the
1211 low bits. */
1212 val =
1213 ((val >> 16) +
1214 ((val & 0x8000) !=
1215 0)) & 0xffff;
1216
1217 insn = (insn & ~0xffff) | val;
1218 *l->addr = insn;
1219
1220 next = l->next;
1221 free(l);
1222 l = next;
1223 }
1224
1225 ifile->mips_hi16_list = NULL;
1226 }
1227
1228 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1229 val = v + vallo;
1230 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1231 *loc = insnlo;
1232 break;
1233 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001234
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001235#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001236
Eric Andersen3b1a7442003-12-24 20:30:45 +00001237 case R_PPC_ADDR16_HA:
1238 *(unsigned short *)loc = (v + 0x8000) >> 16;
1239 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001240
Eric Andersen3b1a7442003-12-24 20:30:45 +00001241 case R_PPC_ADDR16_HI:
1242 *(unsigned short *)loc = v >> 16;
1243 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001244
Eric Andersen3b1a7442003-12-24 20:30:45 +00001245 case R_PPC_ADDR16_LO:
1246 *(unsigned short *)loc = v;
1247 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001248
Eric Andersen3b1a7442003-12-24 20:30:45 +00001249 case R_PPC_REL24:
1250 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001251
Eric Andersen3b1a7442003-12-24 20:30:45 +00001252 case R_PPC_REL32:
1253 *loc = v - dot;
1254 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001255
Eric Andersen3b1a7442003-12-24 20:30:45 +00001256 case R_PPC_ADDR32:
1257 *loc = v;
1258 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001259
1260#elif defined(__sh__)
1261
Eric Andersen3b1a7442003-12-24 20:30:45 +00001262 case R_SH_NONE:
1263 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001264
Eric Andersen3b1a7442003-12-24 20:30:45 +00001265 case R_SH_DIR32:
1266 *loc += v;
1267 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001268
Eric Andersen3b1a7442003-12-24 20:30:45 +00001269 case R_SH_REL32:
1270 *loc += v - dot;
1271 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001272
Eric Andersen3b1a7442003-12-24 20:30:45 +00001273 case R_SH_PLT32:
1274 *loc = v - dot;
1275 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001276
Eric Andersen3b1a7442003-12-24 20:30:45 +00001277 case R_SH_GLOB_DAT:
1278 case R_SH_JMP_SLOT:
1279 *loc = v;
1280 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001281
Eric Andersen3b1a7442003-12-24 20:30:45 +00001282 case R_SH_RELATIVE:
1283 *loc = f->baseaddr + rel->r_addend;
1284 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001285
Eric Andersen3b1a7442003-12-24 20:30:45 +00001286 case R_SH_GOTPC:
1287 assert(got != 0);
1288 *loc = got - dot + rel->r_addend;
1289 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001290
Eric Andersen3b1a7442003-12-24 20:30:45 +00001291 case R_SH_GOT32:
1292 goto bb_use_got;
1293
1294 case R_SH_GOTOFF:
1295 assert(got != 0);
1296 *loc = v - got;
1297 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001298
Eric Andersenbf833552003-08-13 19:56:33 +00001299#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001300 case R_SH_IMM_MEDLOW16:
1301 case R_SH_IMM_LOW16:
1302 {
1303 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001304
Eric Andersen3b1a7442003-12-24 20:30:45 +00001305 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1306 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001307
Eric Andersen3b1a7442003-12-24 20:30:45 +00001308 /*
1309 * movi and shori have the format:
1310 *
1311 * | op | imm | reg | reserved |
1312 * 31..26 25..10 9.. 4 3 .. 0
1313 *
1314 * so we simply mask and or in imm.
1315 */
1316 word = *loc & ~0x3fffc00;
1317 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 }
Eric Andersenbf833552003-08-13 19:56:33 +00001323
Eric Andersen3b1a7442003-12-24 20:30:45 +00001324 case R_SH_IMM_MEDLOW16_PCREL:
1325 case R_SH_IMM_LOW16_PCREL:
1326 {
1327 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001328
Eric Andersen3b1a7442003-12-24 20:30:45 +00001329 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001330
Eric Andersen3b1a7442003-12-24 20:30:45 +00001331 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001332
Eric Andersen3b1a7442003-12-24 20:30:45 +00001333 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1334 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001335
Eric Andersen3b1a7442003-12-24 20:30:45 +00001336 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001337
Eric Andersen3b1a7442003-12-24 20:30:45 +00001338 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001339
Eric Andersen3b1a7442003-12-24 20:30:45 +00001340 break;
1341 }
Eric Andersenbf833552003-08-13 19:56:33 +00001342#endif /* __SH5__ */
1343#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001344
Eric Andersen3b1a7442003-12-24 20:30:45 +00001345 default:
1346 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1347 ret = obj_reloc_unhandled;
1348 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001349
1350#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001351 case R_V850_NONE:
1352 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001353
Eric Andersen3b1a7442003-12-24 20:30:45 +00001354 case R_V850_32:
1355 /* We write two shorts instead of a long because even
1356 32-bit insns only need half-word alignment, but
1357 32-bit data needs to be long-word aligned. */
1358 v += ((unsigned short *)loc)[0];
1359 v += ((unsigned short *)loc)[1] << 16;
1360 ((unsigned short *)loc)[0] = v & 0xffff;
1361 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1362 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001363
Eric Andersen3b1a7442003-12-24 20:30:45 +00001364 case R_V850_22_PCREL:
1365 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001366#endif
1367
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001368#if defined (__cris__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001369 case R_CRIS_NONE:
1370 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001371
Eric Andersen3b1a7442003-12-24 20:30:45 +00001372 case R_CRIS_32:
1373 /* CRIS keeps the relocation value in the r_addend field and
1374 * should not use whats in *loc at all
1375 */
1376 *loc = v;
1377 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001378#endif
1379
Eric Andersena6f6a952004-05-26 12:06:38 +00001380#if defined(__H8300H__) || defined(__H8300S__)
Eric Andersenee70fa52004-05-26 11:38:46 +00001381 case R_H8_DIR24R8:
1382 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
1383 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
1384 break;
1385 case R_H8_DIR24A8:
1386 *loc += v;
1387 break;
1388 case R_H8_DIR32:
1389 case R_H8_DIR32A16:
1390 *loc += v;
1391 break;
1392 case R_H8_PCREL16:
1393 v -= dot + 2;
1394 if ((Elf32_Sword)v > 0x7fff ||
1395 (Elf32_Sword)v < -(Elf32_Sword)0x8000)
1396 ret = obj_reloc_overflow;
1397 else
1398 *(unsigned short *)loc = v;
1399 break;
1400 case R_H8_PCREL8:
1401 v -= dot + 1;
1402 if ((Elf32_Sword)v > 0x7f ||
1403 (Elf32_Sword)v < -(Elf32_Sword)0x80)
1404 ret = obj_reloc_overflow;
1405 else
1406 *(unsigned char *)loc = v;
1407 break;
1408#endif
1409
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001410#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001411
Eric Andersen3b1a7442003-12-24 20:30:45 +00001412bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001413
Eric Andersen3b1a7442003-12-24 20:30:45 +00001414 /* find the plt entry and initialize it if necessary */
1415 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001416
Eric Andersencffd5022002-05-24 06:50:15 +00001417#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001418 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1419 pe = pe->next;
1420 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001421#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001422 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001423#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001424
Eric Andersen3b1a7442003-12-24 20:30:45 +00001425 if (! pe->inited) {
1426 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001427
Eric Andersen3b1a7442003-12-24 20:30:45 +00001428 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001429
1430#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001431 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1432 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001433#endif
1434#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001435 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1436 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1437 ip[2] = 0x7d6903a6; /* mtctr r11 */
1438 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001439#endif
Miles Baderae28b042002-04-01 09:34:25 +00001440#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001441 /* We have to trash a register, so we assume that any control
1442 transfer more than 21-bits away must be a function call
1443 (so we can use a call-clobbered register). */
1444 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1445 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001446#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001447 pe->inited = 1;
1448 }
Eric Andersen21adca72000-12-06 18:18:26 +00001449
Eric Andersen3b1a7442003-12-24 20:30:45 +00001450 /* relative distance to target */
1451 v -= dot;
1452 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001453#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001454 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001455#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001456 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001457#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001458 /* go via the plt */
1459 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001460
1461#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001463#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001464 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001465#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001467
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001469#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001470 /* Convert to words. */
1471 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001472
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001474#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001475#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001477#endif
Miles Baderae28b042002-04-01 09:34:25 +00001478#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 /* We write two shorts instead of a long because even 32-bit insns
1480 only need half-word alignment, but the 32-bit data write needs
1481 to be long-word aligned. */
1482 ((unsigned short *)loc)[0] =
1483 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1484 | ((v >> 16) & 0x3f); /* offs high part */
1485 ((unsigned short *)loc)[1] =
1486 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001487#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001489#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001490
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001491#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001493
Eric Andersen3b1a7442003-12-24 20:30:45 +00001494 assert(isym != NULL);
1495 /* needs an entry in the .got: set it, once */
1496 if (!isym->gotent.inited) {
1497 isym->gotent.inited = 1;
1498 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1499 }
1500 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001501#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001502 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001503#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001504 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001505#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001507
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001508#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001509 }
1510
1511 return ret;
1512}
1513
Eric Andersencffd5022002-05-24 06:50:15 +00001514
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001515#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001516
1517static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1518 int offset, int size)
1519{
1520 struct arch_list_entry *pe;
1521
1522 for (pe = *list; pe != NULL; pe = pe->next) {
1523 if (pe->addend == rel->r_addend) {
1524 break;
1525 }
1526 }
1527
1528 if (pe == NULL) {
1529 pe = xmalloc(sizeof(struct arch_list_entry));
1530 pe->next = *list;
1531 pe->addend = rel->r_addend;
1532 pe->offset = offset;
1533 pe->inited = 0;
1534 *list = pe;
1535 return size;
1536 }
1537 return 0;
1538}
1539
1540#endif
1541
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001542#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001543
1544static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1545 int offset, int size)
1546{
1547 if (single->allocated == 0) {
1548 single->allocated = 1;
1549 single->offset = offset;
1550 single->inited = 0;
1551 return size;
1552 }
1553 return 0;
1554}
1555
1556#endif
1557
1558#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1559
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001560static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001561 int offset, int size)
1562{
1563 struct obj_section *myrelsec = obj_find_section(f, name);
1564
1565 if (offset == 0) {
1566 offset += size;
1567 }
1568
1569 if (myrelsec) {
1570 obj_extend_section(myrelsec, offset);
1571 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001572 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001573 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001574 assert(myrelsec);
1575 }
1576
1577 return myrelsec;
1578}
1579
1580#endif
1581
1582static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001583{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001584#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001585 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001586 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001587#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001588 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001589#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001590#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001591 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001592#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001593 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001594 ElfW(RelM) *rel, *relend;
1595 ElfW(Sym) *symtab, *extsym;
1596 const char *strtab, *name;
1597 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001598
Eric Andersen21adca72000-12-06 18:18:26 +00001599 for (i = 0; i < f->header.e_shnum; ++i) {
1600 relsec = f->sections[i];
1601 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001602 continue;
1603
Eric Andersen21adca72000-12-06 18:18:26 +00001604 symsec = f->sections[relsec->header.sh_link];
1605 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001606
Eric Andersen21adca72000-12-06 18:18:26 +00001607 rel = (ElfW(RelM) *) relsec->contents;
1608 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1609 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001610 strtab = (const char *) strsec->contents;
1611
1612 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001613 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001614
Eric Andersencffd5022002-05-24 06:50:15 +00001615#if defined(CONFIG_USE_GOT_ENTRIES)
1616 got_allocate = 0;
1617#endif
1618#if defined(CONFIG_USE_PLT_ENTRIES)
1619 plt_allocate = 0;
1620#endif
1621
Eric Andersen9f16d612000-06-12 23:11:16 +00001622 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001623#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001624 case R_ARM_PC24:
1625 case R_ARM_PLT32:
1626 plt_allocate = 1;
1627 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001628
Eric Andersen3b1a7442003-12-24 20:30:45 +00001629 case R_ARM_GOTOFF:
1630 case R_ARM_GOTPC:
1631 got_needed = 1;
1632 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001633
Eric Andersen3b1a7442003-12-24 20:30:45 +00001634 case R_ARM_GOT32:
1635 got_allocate = 1;
1636 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001637
Eric Andersen21adca72000-12-06 18:18:26 +00001638#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001639 case R_386_GOTPC:
1640 case R_386_GOTOFF:
1641 got_needed = 1;
1642 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001643
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 case R_386_GOT32:
1645 got_allocate = 1;
1646 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001647
1648#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 case R_PPC_REL24:
1650 plt_allocate = 1;
1651 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001652
1653#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 case R_68K_GOT32:
1655 got_allocate = 1;
1656 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001657
Eric Andersen16451a02004-03-19 12:16:18 +00001658#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 case R_68K_GOTOFF:
1660 got_needed = 1;
1661 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001662#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001663
1664#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001666 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001667 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001668
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 case R_SH_GOTPC:
1670 case R_SH_GOTOFF:
1671 got_needed = 1;
1672 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001673
1674#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 case R_V850_22_PCREL:
1676 plt_needed = 1;
1677 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001678
1679#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001680 default:
1681 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001682 }
1683
Eric Andersen21adca72000-12-06 18:18:26 +00001684 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001685 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001686 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001687 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001688 }
1689 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001690#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001691 if (got_allocate) {
1692 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001693 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001695
1696 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001697 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001698#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001699#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001700 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001701#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001702 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001703 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001704 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001705#else
1706 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001707 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001708 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001709#endif
1710 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001711 }
1712#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001713 }
Miles Baderae28b042002-04-01 09:34:25 +00001714 }
Eric Andersen21adca72000-12-06 18:18:26 +00001715
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001716#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001717 if (got_needed) {
1718 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001719 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001720 }
Eric Andersen21adca72000-12-06 18:18:26 +00001721#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001722
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001723#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001724 if (plt_needed) {
1725 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001726 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001727 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001728#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001729
1730#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001731}
1732
Eric Andersen9f16d612000-06-12 23:11:16 +00001733/*======================================================================*/
1734
1735/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001736static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001737{
1738 unsigned long h = 0;
1739 unsigned long g;
1740 unsigned char ch;
1741
1742 while (n > 0) {
1743 ch = *name++;
1744 h = (h << 4) + ch;
1745 if ((g = (h & 0xf0000000)) != 0) {
1746 h ^= g >> 24;
1747 h &= ~g;
1748 }
1749 n--;
1750 }
1751 return h;
1752}
1753
Eric Andersen044228d2001-07-17 01:12:36 +00001754static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001755{
1756 return obj_elf_hash_n(name, strlen(name));
1757}
1758
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001759#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001760/* String comparison for non-co-versioned kernel and module. */
1761
1762static int ncv_strcmp(const char *a, const char *b)
1763{
1764 size_t alen = strlen(a), blen = strlen(b);
1765
1766 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1767 return strncmp(a, b, alen);
1768 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1769 return strncmp(a, b, blen);
1770 else
1771 return strcmp(a, b);
1772}
1773
1774/* String hashing for non-co-versioned kernel and module. Here
1775 we are simply forced to drop the crc from the hash. */
1776
1777static unsigned long ncv_symbol_hash(const char *str)
1778{
1779 size_t len = strlen(str);
1780 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1781 len -= 10;
1782 return obj_elf_hash_n(str, len);
1783}
1784
Eric Andersen044228d2001-07-17 01:12:36 +00001785static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001786obj_set_symbol_compare(struct obj_file *f,
1787 int (*cmp) (const char *, const char *),
1788 unsigned long (*hash) (const char *))
1789{
1790 if (cmp)
1791 f->symbol_cmp = cmp;
1792 if (hash) {
1793 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1794 int i;
1795
1796 f->symbol_hash = hash;
1797
1798 memcpy(tmptab, f->symtab, sizeof(tmptab));
1799 memset(f->symtab, 0, sizeof(f->symtab));
1800
1801 for (i = 0; i < HASH_BUCKETS; ++i)
1802 for (sym = tmptab[i]; sym; sym = next) {
1803 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1804 next = sym->next;
1805 sym->next = f->symtab[h];
1806 f->symtab[h] = sym;
1807 }
1808 }
1809}
1810
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001811#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001812
Eric Andersen044228d2001-07-17 01:12:36 +00001813static struct obj_symbol *
1814obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001815 unsigned long symidx, int info,
1816 int secidx, ElfW(Addr) value,
1817 unsigned long size)
1818{
1819 struct obj_symbol *sym;
1820 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1821 int n_type = ELFW(ST_TYPE) (info);
1822 int n_binding = ELFW(ST_BIND) (info);
1823
1824 for (sym = f->symtab[hash]; sym; sym = sym->next)
1825 if (f->symbol_cmp(sym->name, name) == 0) {
1826 int o_secidx = sym->secidx;
1827 int o_info = sym->info;
1828 int o_type = ELFW(ST_TYPE) (o_info);
1829 int o_binding = ELFW(ST_BIND) (o_info);
1830
1831 /* A redefinition! Is it legal? */
1832
1833 if (secidx == SHN_UNDEF)
1834 return sym;
1835 else if (o_secidx == SHN_UNDEF)
1836 goto found;
1837 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1838 /* Cope with local and global symbols of the same name
1839 in the same object file, as might have been created
1840 by ld -r. The only reason locals are now seen at this
1841 level at all is so that we can do semi-sensible things
1842 with parameters. */
1843
1844 struct obj_symbol *nsym, **p;
1845
1846 nsym = arch_new_symbol();
1847 nsym->next = sym->next;
1848 nsym->ksymidx = -1;
1849
1850 /* Excise the old (local) symbol from the hash chain. */
1851 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1852 continue;
1853 *p = sym = nsym;
1854 goto found;
1855 } else if (n_binding == STB_LOCAL) {
1856 /* Another symbol of the same name has already been defined.
1857 Just add this to the local table. */
1858 sym = arch_new_symbol();
1859 sym->next = NULL;
1860 sym->ksymidx = -1;
1861 f->local_symtab[symidx] = sym;
1862 goto found;
1863 } else if (n_binding == STB_WEAK)
1864 return sym;
1865 else if (o_binding == STB_WEAK)
1866 goto found;
1867 /* Don't unify COMMON symbols with object types the programmer
1868 doesn't expect. */
1869 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001870 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001871 return sym;
1872 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001873 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001874 goto found;
1875 else {
1876 /* Don't report an error if the symbol is coming from
1877 the kernel or some external module. */
1878 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001879 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001880 return sym;
1881 }
1882 }
1883
1884 /* Completely new symbol. */
1885 sym = arch_new_symbol();
1886 sym->next = f->symtab[hash];
1887 f->symtab[hash] = sym;
1888 sym->ksymidx = -1;
1889
Eric Andersen66ca9482001-06-28 21:36:06 +00001890 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1891 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001892 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001893 name, (long) symidx, (long) f->local_symtab_size);
1894 else
1895 f->local_symtab[symidx] = sym;
1896 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001897
Eric Andersen3b1a7442003-12-24 20:30:45 +00001898found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001899 sym->name = name;
1900 sym->value = value;
1901 sym->size = size;
1902 sym->secidx = secidx;
1903 sym->info = info;
1904
1905 return sym;
1906}
1907
Eric Andersen044228d2001-07-17 01:12:36 +00001908static struct obj_symbol *
1909obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001910{
1911 struct obj_symbol *sym;
1912 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1913
1914 for (sym = f->symtab[hash]; sym; sym = sym->next)
1915 if (f->symbol_cmp(sym->name, name) == 0)
1916 return sym;
1917
1918 return NULL;
1919}
1920
Eric Andersen044228d2001-07-17 01:12:36 +00001921static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001922 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1923{
1924 if (sym) {
1925 if (sym->secidx >= SHN_LORESERVE)
1926 return sym->value;
1927
1928 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1929 } else {
1930 /* As a special case, a NULL sym has value zero. */
1931 return 0;
1932 }
1933}
1934
Eric Andersen044228d2001-07-17 01:12:36 +00001935static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001936{
1937 int i, n = f->header.e_shnum;
1938
1939 for (i = 0; i < n; ++i)
1940 if (strcmp(f->sections[i]->name, name) == 0)
1941 return f->sections[i];
1942
1943 return NULL;
1944}
1945
1946static int obj_load_order_prio(struct obj_section *a)
1947{
1948 unsigned long af, ac;
1949
1950 af = a->header.sh_flags;
1951
1952 ac = 0;
1953 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001954 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001955 ac |= 32;
1956 if (af & SHF_ALLOC)
1957 ac |= 16;
1958 if (!(af & SHF_WRITE))
1959 ac |= 8;
1960 if (af & SHF_EXECINSTR)
1961 ac |= 4;
1962 if (a->header.sh_type != SHT_NOBITS)
1963 ac |= 2;
1964
1965 return ac;
1966}
1967
Eric Andersen044228d2001-07-17 01:12:36 +00001968static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001969obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1970{
1971 struct obj_section **p;
1972 int prio = obj_load_order_prio(sec);
1973 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1974 if (obj_load_order_prio(*p) < prio)
1975 break;
1976 sec->load_next = *p;
1977 *p = sec;
1978}
1979
Eric Andersen044228d2001-07-17 01:12:36 +00001980static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001981 const char *name,
1982 unsigned long align,
1983 unsigned long size)
1984{
1985 int newidx = f->header.e_shnum++;
1986 struct obj_section *sec;
1987
1988 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1989 f->sections[newidx] = sec = arch_new_section();
1990
1991 memset(sec, 0, sizeof(*sec));
1992 sec->header.sh_type = SHT_PROGBITS;
1993 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1994 sec->header.sh_size = size;
1995 sec->header.sh_addralign = align;
1996 sec->name = name;
1997 sec->idx = newidx;
1998 if (size)
1999 sec->contents = xmalloc(size);
2000
2001 obj_insert_section_load_order(f, sec);
2002
2003 return sec;
2004}
2005
Eric Andersen044228d2001-07-17 01:12:36 +00002006static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002007 const char *name,
2008 unsigned long align,
2009 unsigned long size)
2010{
2011 int newidx = f->header.e_shnum++;
2012 struct obj_section *sec;
2013
2014 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2015 f->sections[newidx] = sec = arch_new_section();
2016
2017 memset(sec, 0, sizeof(*sec));
2018 sec->header.sh_type = SHT_PROGBITS;
2019 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2020 sec->header.sh_size = size;
2021 sec->header.sh_addralign = align;
2022 sec->name = name;
2023 sec->idx = newidx;
2024 if (size)
2025 sec->contents = xmalloc(size);
2026
2027 sec->load_next = f->load_order;
2028 f->load_order = sec;
2029 if (f->load_order_search_start == &f->load_order)
2030 f->load_order_search_start = &sec->load_next;
2031
2032 return sec;
2033}
2034
Eric Andersen044228d2001-07-17 01:12:36 +00002035static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002036{
2037 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002038 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002039 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2040 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002041 return sec->contents + oldsize;
2042}
2043
2044
Eric Andersen9f16d612000-06-12 23:11:16 +00002045/* Conditionally add the symbols from the given symbol set to the
2046 new module. */
2047
2048static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002049add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002050 int idx, struct new_module_symbol *syms, size_t nsyms)
2051{
2052 struct new_module_symbol *s;
2053 size_t i;
2054 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002055#ifdef SYMBOL_PREFIX
2056 char *name_buf = 0;
2057 size_t name_alloced_size = 0;
2058#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002059#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2060 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002061
Glenn L McGrath759515c2003-08-30 06:00:33 +00002062 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002063#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002064 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002065 /* Only add symbols that are already marked external.
2066 If we override locals we may cause problems for
2067 argument initialization. We will also create a false
2068 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002069 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002070 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002071
Glenn L McGrath759515c2003-08-30 06:00:33 +00002072 /* GPL licensed modules can use symbols exported with
2073 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2074 * exported names. Non-GPL modules never see any GPLONLY_
2075 * symbols so they cannot fudge it by adding the prefix on
2076 * their references.
2077 */
2078 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002079#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002080 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002081 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002082 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002083#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002084 continue;
2085 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002086 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002087
Miles Baderae28b042002-04-01 09:34:25 +00002088#ifdef SYMBOL_PREFIX
2089 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2090 kernel exports `C names', but module object files
2091 reference `linker names'). */
2092 size_t extra = sizeof SYMBOL_PREFIX;
2093 size_t name_size = strlen (name) + extra;
2094 if (name_size > name_alloced_size) {
2095 name_alloced_size = name_size * 2;
2096 name_buf = alloca (name_alloced_size);
2097 }
2098 strcpy (name_buf, SYMBOL_PREFIX);
2099 strcpy (name_buf + extra - 1, name);
2100 name = name_buf;
2101#endif /* SYMBOL_PREFIX */
2102
2103 sym = obj_find_symbol(f, name);
2104 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
2105#ifdef SYMBOL_PREFIX
2106 /* Put NAME_BUF into more permanent storage. */
2107 name = xmalloc (name_size);
2108 strcpy (name, name_buf);
2109#endif
2110 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002111 ELFW(ST_INFO) (STB_GLOBAL,
2112 STT_NOTYPE),
2113 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002114 /* Did our symbol just get installed? If so, mark the
2115 module as "used". */
2116 if (sym->secidx == idx)
2117 used = 1;
2118 }
2119 }
2120
2121 return used;
2122}
2123
2124static void add_kernel_symbols(struct obj_file *f)
2125{
2126 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002127 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002128
2129 /* Add module symbols first. */
2130
2131 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2132 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002133 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2134 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002135
2136 n_ext_modules_used = nused;
2137
2138 /* And finally the symbols from the kernel proper. */
2139
2140 if (nksyms)
2141 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2142}
2143
2144static char *get_modinfo_value(struct obj_file *f, const char *key)
2145{
2146 struct obj_section *sec;
2147 char *p, *v, *n, *ep;
2148 size_t klen = strlen(key);
2149
2150 sec = obj_find_section(f, ".modinfo");
2151 if (sec == NULL)
2152 return NULL;
2153 p = sec->contents;
2154 ep = p + sec->header.sh_size;
2155 while (p < ep) {
2156 v = strchr(p, '=');
2157 n = strchr(p, '\0');
2158 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002159 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002160 return v + 1;
2161 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002162 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002163 return n;
2164 }
2165 p = n + 1;
2166 }
2167
2168 return NULL;
2169}
2170
2171
2172/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002173/* Functions relating to module loading after 2.1.18. */
2174
2175static int
2176new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2177{
2178 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002179 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002180 struct obj_symbol *sym;
2181 char *contents, *loc;
2182 int min, max, n;
2183
2184 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002185 if ((q = strchr(p, '=')) == NULL) {
2186 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002187 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002188 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002189
2190 key = alloca(q - p + 6);
2191 memcpy(key, "parm_", 5);
2192 memcpy(key + 5, p, q - p);
2193 key[q - p + 5] = 0;
2194
2195 p = get_modinfo_value(f, key);
2196 key += 5;
2197 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002198 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002199 return 0;
2200 }
2201
Miles Baderae28b042002-04-01 09:34:25 +00002202#ifdef SYMBOL_PREFIX
2203 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2204 strcpy (sym_name, SYMBOL_PREFIX);
2205 strcat (sym_name, key);
2206#else
2207 sym_name = key;
2208#endif
2209 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002210
2211 /* Also check that the parameter was not resolved from the kernel. */
2212 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002213 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002214 return 0;
2215 }
2216
2217 if (isdigit(*p)) {
2218 min = strtoul(p, &p, 10);
2219 if (*p == '-')
2220 max = strtoul(p + 1, &p, 10);
2221 else
2222 max = min;
2223 } else
2224 min = max = 1;
2225
2226 contents = f->sections[sym->secidx]->contents;
2227 loc = contents + sym->value;
2228 n = (*++q != '\0');
2229
2230 while (1) {
2231 if ((*p == 's') || (*p == 'c')) {
2232 char *str;
2233
2234 /* Do C quoting if we begin with a ", else slurp the lot. */
2235 if (*q == '"') {
2236 char *r;
2237
2238 str = alloca(strlen(q));
2239 for (r = str, q++; *q != '"'; ++q, ++r) {
2240 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002241 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002242 key);
2243 return 0;
2244 } else if (*q == '\\')
2245 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002246 case 'a':
2247 *r = '\a';
2248 break;
2249 case 'b':
2250 *r = '\b';
2251 break;
2252 case 'e':
2253 *r = '\033';
2254 break;
2255 case 'f':
2256 *r = '\f';
2257 break;
2258 case 'n':
2259 *r = '\n';
2260 break;
2261 case 'r':
2262 *r = '\r';
2263 break;
2264 case 't':
2265 *r = '\t';
2266 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002267
Eric Andersen3b1a7442003-12-24 20:30:45 +00002268 case '0':
2269 case '1':
2270 case '2':
2271 case '3':
2272 case '4':
2273 case '5':
2274 case '6':
2275 case '7':
2276 {
2277 int c = *q - '0';
2278 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002279 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002280 if (q[1] >= '0' && q[1] <= '7')
2281 c = (c * 8) + *++q - '0';
2282 }
2283 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002284 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002285 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002286
Eric Andersen3b1a7442003-12-24 20:30:45 +00002287 default:
2288 *r = *q;
2289 break;
2290 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002291 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002292 }
2293 *r = '\0';
2294 ++q;
2295 } else {
2296 char *r;
2297
2298 /* In this case, the string is not quoted. We will break
2299 it using the coma (like for ints). If the user wants to
2300 include comas in a string, he just has to quote it */
2301
2302 /* Search the next coma */
2303 r = strchr(q, ',');
2304
2305 /* Found ? */
2306 if (r != (char *) NULL) {
2307 /* Recopy the current field */
2308 str = alloca(r - q + 1);
2309 memcpy(str, q, r - q);
2310
Eric Andersenaff114c2004-04-14 17:51:38 +00002311 /* I don't know if it is useful, as the previous case
2312 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002313 str[r - q] = '\0';
2314
2315 /* Keep next fields */
2316 q = r;
2317 } else {
2318 /* last string */
2319 str = q;
2320 q = "";
2321 }
2322 }
2323
2324 if (*p == 's') {
2325 /* Normal string */
2326 obj_string_patch(f, sym->secidx, loc - contents, str);
2327 loc += tgt_sizeof_char_p;
2328 } else {
2329 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002330 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002331
2332 /* Get the size of each member */
2333 /* Probably we should do that outside the loop ? */
2334 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002335 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002336 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002337 return 0;
2338 }
2339 charssize = strtoul(p + 1, (char **) NULL, 10);
2340
2341 /* Check length */
2342 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002343 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002344 charssize - 1);
2345 return 0;
2346 }
2347
2348 /* Copy to location */
2349 strcpy((char *) loc, str);
2350 loc += charssize;
2351 }
2352 } else {
2353 long v = strtoul(q, &q, 0);
2354 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002355 case 'b':
2356 *loc++ = v;
2357 break;
2358 case 'h':
2359 *(short *) loc = v;
2360 loc += tgt_sizeof_short;
2361 break;
2362 case 'i':
2363 *(int *) loc = v;
2364 loc += tgt_sizeof_int;
2365 break;
2366 case 'l':
2367 *(long *) loc = v;
2368 loc += tgt_sizeof_long;
2369 break;
2370
2371 default:
2372 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2373 return 0;
2374 }
2375 }
2376
2377retry_end_of_value:
2378 switch (*q) {
2379 case '\0':
2380 goto end_of_arg;
2381
2382 case ' ':
2383 case '\t':
2384 case '\n':
2385 case '\r':
2386 ++q;
2387 goto retry_end_of_value;
2388
2389 case ',':
2390 if (++n > max) {
2391 bb_error_msg("too many values for %s (max %d)", key, max);
2392 return 0;
2393 }
2394 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002395 break;
2396
2397 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002398 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002400 }
2401 }
2402
Eric Andersen3b1a7442003-12-24 20:30:45 +00002403end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002404 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002405 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 return 0;
2407 }
2408
2409 argc--, argv++;
2410 }
2411
2412 return 1;
2413}
2414
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002415#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002416static int new_is_module_checksummed(struct obj_file *f)
2417{
2418 const char *p = get_modinfo_value(f, "using_checksums");
2419 if (p)
2420 return atoi(p);
2421 else
2422 return 0;
2423}
2424
2425/* Get the module's kernel version in the canonical integer form. */
2426
2427static int
2428new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2429{
2430 char *p, *q;
2431 int a, b, c;
2432
2433 p = get_modinfo_value(f, "kernel_version");
2434 if (p == NULL)
2435 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002436 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002437
2438 a = strtoul(p, &p, 10);
2439 if (*p != '.')
2440 return -1;
2441 b = strtoul(p + 1, &p, 10);
2442 if (*p != '.')
2443 return -1;
2444 c = strtoul(p + 1, &q, 10);
2445 if (p + 1 == q)
2446 return -1;
2447
2448 return a << 16 | b << 8 | c;
2449}
2450
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002451#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002452
2453
Eric Andersen9f16d612000-06-12 23:11:16 +00002454/* Fetch the loaded modules, and all currently exported symbols. */
2455
2456static int new_get_kernel_symbols(void)
2457{
2458 char *module_names, *mn;
2459 struct external_module *modules, *m;
2460 struct new_module_symbol *syms, *s;
2461 size_t ret, bufsize, nmod, nsyms, i, j;
2462
2463 /* Collect the loaded modules. */
2464
2465 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002466retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002467 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002468 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002469 module_names = xrealloc(module_names, bufsize = ret);
2470 goto retry_modules_load;
2471 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002472 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002473 return 0;
2474 }
2475
2476 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002477
2478 /* Collect the modules' symbols. */
2479
Mark Whitley94fd4802001-03-12 23:08:34 +00002480 if (nmod){
2481 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2482 memset(modules, 0, nmod * sizeof(*modules));
2483 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002484 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002485 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002486
Mark Whitley94fd4802001-03-12 23:08:34 +00002487 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2488 if (errno == ENOENT) {
2489 /* The module was removed out from underneath us. */
2490 continue;
2491 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002492 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002493 return 0;
2494 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002495
Mark Whitley94fd4802001-03-12 23:08:34 +00002496 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002497retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002498 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2499 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002500 case ENOSPC:
2501 syms = xrealloc(syms, bufsize = ret);
2502 goto retry_mod_sym_load;
2503 case ENOENT:
2504 /* The module was removed out from underneath us. */
2505 continue;
2506 default:
2507 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2508 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002509 }
2510 }
2511 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002512
Mark Whitley94fd4802001-03-12 23:08:34 +00002513 m->name = mn;
2514 m->addr = info.addr;
2515 m->nsyms = nsyms;
2516 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002517
Mark Whitley94fd4802001-03-12 23:08:34 +00002518 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2519 s->name += (unsigned long) syms;
2520 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002521 }
2522 }
2523
2524 /* Collect the kernel's symbols. */
2525
2526 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002527retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002528 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002529 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002530 syms = xrealloc(syms, bufsize = ret);
2531 goto retry_kern_sym_load;
2532 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002533 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002534 return 0;
2535 }
2536 nksyms = nsyms = ret;
2537 ksyms = syms;
2538
2539 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2540 s->name += (unsigned long) syms;
2541 }
2542 return 1;
2543}
2544
2545
2546/* Return the kernel symbol checksum version, or zero if not used. */
2547
2548static int new_is_kernel_checksummed(void)
2549{
2550 struct new_module_symbol *s;
2551 size_t i;
2552
2553 /* Using_Versions is not the first symbol, but it should be in there. */
2554
2555 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2556 if (strcmp((char *) s->name, "Using_Versions") == 0)
2557 return s->value;
2558
2559 return 0;
2560}
2561
2562
2563static int new_create_this_module(struct obj_file *f, const char *m_name)
2564{
2565 struct obj_section *sec;
2566
2567 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002568 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002569 memset(sec->contents, 0, sizeof(struct new_module));
2570
Miles Baderae28b042002-04-01 09:34:25 +00002571 obj_add_symbol(f, SPFX "__this_module", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002572 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2573 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002574
2575 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002576 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002577
2578 return 1;
2579}
2580
Eric Andersen889dd202003-01-23 04:48:34 +00002581#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2582/* add an entry to the __ksymtab section, creating it if necessary */
2583static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2584{
2585 struct obj_section *sec;
2586 ElfW(Addr) ofs;
2587
2588 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2589 * If __ksymtab is defined but not marked alloc, x out the first character
2590 * (no obj_delete routine) and create a new __ksymtab with the correct
2591 * characteristics.
2592 */
2593 sec = obj_find_section(f, "__ksymtab");
2594 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2595 *((char *)(sec->name)) = 'x'; /* override const */
2596 sec = NULL;
2597 }
2598 if (!sec)
2599 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002600 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002601 if (!sec)
2602 return;
2603 sec->header.sh_flags |= SHF_ALLOC;
2604 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002605 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002606 ofs = sec->header.sh_size;
2607 obj_symbol_patch(f, sec->idx, ofs, sym);
2608 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2609 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2610}
2611#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002612
2613static int new_create_module_ksymtab(struct obj_file *f)
2614{
2615 struct obj_section *sec;
2616 int i;
2617
2618 /* We must always add the module references. */
2619
2620 if (n_ext_modules_used) {
2621 struct new_module_ref *dep;
2622 struct obj_symbol *tm;
2623
2624 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002625 (sizeof(struct new_module_ref)
2626 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002627 if (!sec)
2628 return 0;
2629
Miles Baderae28b042002-04-01 09:34:25 +00002630 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002631 dep = (struct new_module_ref *) sec->contents;
2632 for (i = 0; i < n_ext_modules; ++i)
2633 if (ext_modules[i].used) {
2634 dep->dep = ext_modules[i].addr;
2635 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002636 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002637 dep->next_ref = 0;
2638 ++dep;
2639 }
2640 }
2641
2642 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2643 size_t nsyms;
2644 int *loaded;
2645
2646 sec =
2647 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002648 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002649
2650 /* We don't want to export symbols residing in sections that
2651 aren't loaded. There are a number of these created so that
2652 we make sure certain module options don't appear twice. */
2653
2654 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2655 while (--i >= 0)
2656 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2657
2658 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2659 struct obj_symbol *sym;
2660 for (sym = f->symtab[i]; sym; sym = sym->next)
2661 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002662 && sym->secidx <= SHN_HIRESERVE
2663 && (sym->secidx >= SHN_LORESERVE
2664 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002665 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2666
2667 obj_symbol_patch(f, sec->idx, ofs, sym);
2668 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002669 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002670
2671 nsyms++;
2672 }
2673 }
2674
2675 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2676 }
2677
2678 return 1;
2679}
2680
2681
2682static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002683new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002684{
2685 struct new_module *module;
2686 struct obj_section *sec;
2687 void *image;
2688 int ret;
2689 tgt_long m_addr;
2690
2691 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002692 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002693 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002694 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002695 module = (struct new_module *) sec->contents;
2696 m_addr = sec->header.sh_addr;
2697
2698 module->size_of_struct = sizeof(*module);
2699 module->size = m_size;
2700 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2701
2702 sec = obj_find_section(f, "__ksymtab");
2703 if (sec && sec->header.sh_size) {
2704 module->syms = sec->header.sh_addr;
2705 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2706 }
2707
2708 if (n_ext_modules_used) {
2709 sec = obj_find_section(f, ".kmodtab");
2710 module->deps = sec->header.sh_addr;
2711 module->ndeps = n_ext_modules_used;
2712 }
2713
2714 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002715 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002717 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002718
2719 sec = obj_find_section(f, "__ex_table");
2720 if (sec) {
2721 module->ex_table_start = sec->header.sh_addr;
2722 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2723 }
2724
2725 sec = obj_find_section(f, ".text.init");
2726 if (sec) {
2727 module->runsize = sec->header.sh_addr - m_addr;
2728 }
2729 sec = obj_find_section(f, ".data.init");
2730 if (sec) {
2731 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002732 module->runsize > sec->header.sh_addr - m_addr)
2733 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002734 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002735 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2736 if (sec && sec->header.sh_size) {
2737 module->archdata_start = (void*)sec->header.sh_addr;
2738 module->archdata_end = module->archdata_start + sec->header.sh_size;
2739 }
2740 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2741 if (sec && sec->header.sh_size) {
2742 module->kallsyms_start = (void*)sec->header.sh_addr;
2743 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2744 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002745
Eric Andersen9f16d612000-06-12 23:11:16 +00002746 /* Whew! All of the initialization is complete. Collect the final
2747 module image and give it to the kernel. */
2748
2749 image = xmalloc(m_size);
2750 obj_create_image(f, image);
2751
Eric Andersencb3b9b12004-06-22 11:50:52 +00002752 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002753 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002754 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002755
2756 free(image);
2757
2758 return ret == 0;
2759}
2760
Eric Andersen9f16d612000-06-12 23:11:16 +00002761
2762/*======================================================================*/
2763
Eric Andersen044228d2001-07-17 01:12:36 +00002764static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002765obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2766 const char *string)
2767{
2768 struct obj_string_patch *p;
2769 struct obj_section *strsec;
2770 size_t len = strlen(string) + 1;
2771 char *loc;
2772
2773 p = xmalloc(sizeof(*p));
2774 p->next = f->string_patches;
2775 p->reloc_secidx = secidx;
2776 p->reloc_offset = offset;
2777 f->string_patches = p;
2778
2779 strsec = obj_find_section(f, ".kstrtab");
2780 if (strsec == NULL) {
2781 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2782 p->string_offset = 0;
2783 loc = strsec->contents;
2784 } else {
2785 p->string_offset = strsec->header.sh_size;
2786 loc = obj_extend_section(strsec, len);
2787 }
2788 memcpy(loc, string, len);
2789
2790 return 1;
2791}
2792
Eric Andersen044228d2001-07-17 01:12:36 +00002793static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002794obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2795 struct obj_symbol *sym)
2796{
2797 struct obj_symbol_patch *p;
2798
2799 p = xmalloc(sizeof(*p));
2800 p->next = f->symbol_patches;
2801 p->reloc_secidx = secidx;
2802 p->reloc_offset = offset;
2803 p->sym = sym;
2804 f->symbol_patches = p;
2805
2806 return 1;
2807}
2808
Eric Andersen044228d2001-07-17 01:12:36 +00002809static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002810{
2811 unsigned long i;
2812 int ret = 1;
2813
2814 for (i = 0; i < HASH_BUCKETS; ++i) {
2815 struct obj_symbol *sym;
2816 for (sym = f->symtab[i]; sym; sym = sym->next)
2817 if (sym->secidx == SHN_UNDEF) {
2818 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2819 sym->secidx = SHN_ABS;
2820 sym->value = 0;
2821 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002822 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002823 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00002824 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002825 ret = 0;
2826 }
2827 }
2828 }
2829
2830 return ret;
2831}
2832
Eric Andersen044228d2001-07-17 01:12:36 +00002833static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002834{
2835 struct common_entry {
2836 struct common_entry *next;
2837 struct obj_symbol *sym;
2838 } *common_head = NULL;
2839
2840 unsigned long i;
2841
2842 for (i = 0; i < HASH_BUCKETS; ++i) {
2843 struct obj_symbol *sym;
2844 for (sym = f->symtab[i]; sym; sym = sym->next)
2845 if (sym->secidx == SHN_COMMON) {
2846 /* Collect all COMMON symbols and sort them by size so as to
2847 minimize space wasted by alignment requirements. */
2848 {
2849 struct common_entry **p, *n;
2850 for (p = &common_head; *p; p = &(*p)->next)
2851 if (sym->size <= (*p)->sym->size)
2852 break;
2853
2854 n = alloca(sizeof(*n));
2855 n->next = *p;
2856 n->sym = sym;
2857 *p = n;
2858 }
2859 }
2860 }
2861
2862 for (i = 1; i < f->local_symtab_size; ++i) {
2863 struct obj_symbol *sym = f->local_symtab[i];
2864 if (sym && sym->secidx == SHN_COMMON) {
2865 struct common_entry **p, *n;
2866 for (p = &common_head; *p; p = &(*p)->next)
2867 if (sym == (*p)->sym)
2868 break;
2869 else if (sym->size < (*p)->sym->size) {
2870 n = alloca(sizeof(*n));
2871 n->next = *p;
2872 n->sym = sym;
2873 *p = n;
2874 break;
2875 }
2876 }
2877 }
2878
2879 if (common_head) {
2880 /* Find the bss section. */
2881 for (i = 0; i < f->header.e_shnum; ++i)
2882 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2883 break;
2884
2885 /* If for some reason there hadn't been one, create one. */
2886 if (i == f->header.e_shnum) {
2887 struct obj_section *sec;
2888
2889 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2890 f->sections[i] = sec = arch_new_section();
2891 f->header.e_shnum = i + 1;
2892
2893 memset(sec, 0, sizeof(*sec));
2894 sec->header.sh_type = SHT_PROGBITS;
2895 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2896 sec->name = ".bss";
2897 sec->idx = i;
2898 }
2899
2900 /* Allocate the COMMONS. */
2901 {
2902 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2903 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2904 struct common_entry *c;
2905
2906 for (c = common_head; c; c = c->next) {
2907 ElfW(Addr) align = c->sym->value;
2908
2909 if (align > max_align)
2910 max_align = align;
2911 if (bss_size & (align - 1))
2912 bss_size = (bss_size | (align - 1)) + 1;
2913
2914 c->sym->secidx = i;
2915 c->sym->value = bss_size;
2916
2917 bss_size += c->sym->size;
2918 }
2919
2920 f->sections[i]->header.sh_size = bss_size;
2921 f->sections[i]->header.sh_addralign = max_align;
2922 }
2923 }
2924
2925 /* For the sake of patch relocation and parameter initialization,
2926 allocate zeroed data for NOBITS sections now. Note that after
2927 this we cannot assume NOBITS are really empty. */
2928 for (i = 0; i < f->header.e_shnum; ++i) {
2929 struct obj_section *s = f->sections[i];
2930 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002931 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002932 s->contents = memset(xmalloc(s->header.sh_size),
2933 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002934 else
2935 s->contents = NULL;
2936
Eric Andersen9f16d612000-06-12 23:11:16 +00002937 s->header.sh_type = SHT_PROGBITS;
2938 }
2939 }
2940}
2941
Eric Andersen044228d2001-07-17 01:12:36 +00002942static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002943{
2944 unsigned long dot = 0;
2945 struct obj_section *sec;
2946
2947 /* Finalize the positions of the sections relative to one another. */
2948
2949 for (sec = f->load_order; sec; sec = sec->load_next) {
2950 ElfW(Addr) align;
2951
2952 align = sec->header.sh_addralign;
2953 if (align && (dot & (align - 1)))
2954 dot = (dot | (align - 1)) + 1;
2955
2956 sec->header.sh_addr = dot;
2957 dot += sec->header.sh_size;
2958 }
2959
2960 return dot;
2961}
2962
Eric Andersen044228d2001-07-17 01:12:36 +00002963static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002964{
2965 int i, n = f->header.e_shnum;
2966 int ret = 1;
2967
2968 /* Finalize the addresses of the sections. */
2969
2970 f->baseaddr = base;
2971 for (i = 0; i < n; ++i)
2972 f->sections[i]->header.sh_addr += base;
2973
2974 /* And iterate over all of the relocations. */
2975
2976 for (i = 0; i < n; ++i) {
2977 struct obj_section *relsec, *symsec, *targsec, *strsec;
2978 ElfW(RelM) * rel, *relend;
2979 ElfW(Sym) * symtab;
2980 const char *strtab;
2981
2982 relsec = f->sections[i];
2983 if (relsec->header.sh_type != SHT_RELM)
2984 continue;
2985
2986 symsec = f->sections[relsec->header.sh_link];
2987 targsec = f->sections[relsec->header.sh_info];
2988 strsec = f->sections[symsec->header.sh_link];
2989
2990 rel = (ElfW(RelM) *) relsec->contents;
2991 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2992 symtab = (ElfW(Sym) *) symsec->contents;
2993 strtab = (const char *) strsec->contents;
2994
2995 for (; rel < relend; ++rel) {
2996 ElfW(Addr) value = 0;
2997 struct obj_symbol *intsym = NULL;
2998 unsigned long symndx;
2999 ElfW(Sym) * extsym = 0;
3000 const char *errmsg;
3001
3002 /* Attempt to find a value to use for this relocation. */
3003
3004 symndx = ELFW(R_SYM) (rel->r_info);
3005 if (symndx) {
3006 /* Note we've already checked for undefined symbols. */
3007
3008 extsym = &symtab[symndx];
3009 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3010 /* Local symbols we look up in the local table to be sure
3011 we get the one that is really intended. */
3012 intsym = f->local_symtab[symndx];
3013 } else {
3014 /* Others we look up in the hash table. */
3015 const char *name;
3016 if (extsym->st_name)
3017 name = strtab + extsym->st_name;
3018 else
3019 name = f->sections[extsym->st_shndx]->name;
3020 intsym = obj_find_symbol(f, name);
3021 }
3022
3023 value = obj_symbol_final_value(f, intsym);
3024 intsym->referenced = 1;
3025 }
3026#if SHT_RELM == SHT_RELA
3027#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3028 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3029 if (!extsym || !extsym->st_name ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00003030 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003031#endif
3032 value += rel->r_addend;
3033#endif
3034
3035 /* Do it! */
3036 switch (arch_apply_relocation
3037 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003038 case obj_reloc_ok:
3039 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003040
Eric Andersen3b1a7442003-12-24 20:30:45 +00003041 case obj_reloc_overflow:
3042 errmsg = "Relocation overflow";
3043 goto bad_reloc;
3044 case obj_reloc_dangerous:
3045 errmsg = "Dangerous relocation";
3046 goto bad_reloc;
3047 case obj_reloc_unhandled:
3048 errmsg = "Unhandled relocation";
3049bad_reloc:
3050 if (extsym) {
3051 bb_error_msg("%s of type %ld for %s", errmsg,
3052 (long) ELFW(R_TYPE) (rel->r_info),
3053 strtab + extsym->st_name);
3054 } else {
3055 bb_error_msg("%s of type %ld", errmsg,
3056 (long) ELFW(R_TYPE) (rel->r_info));
3057 }
3058 ret = 0;
3059 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003060 }
3061 }
3062 }
3063
3064 /* Finally, take care of the patches. */
3065
3066 if (f->string_patches) {
3067 struct obj_string_patch *p;
3068 struct obj_section *strsec;
3069 ElfW(Addr) strsec_base;
3070 strsec = obj_find_section(f, ".kstrtab");
3071 strsec_base = strsec->header.sh_addr;
3072
3073 for (p = f->string_patches; p; p = p->next) {
3074 struct obj_section *targsec = f->sections[p->reloc_secidx];
3075 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3076 = strsec_base + p->string_offset;
3077 }
3078 }
3079
3080 if (f->symbol_patches) {
3081 struct obj_symbol_patch *p;
3082
3083 for (p = f->symbol_patches; p; p = p->next) {
3084 struct obj_section *targsec = f->sections[p->reloc_secidx];
3085 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3086 = obj_symbol_final_value(f, p->sym);
3087 }
3088 }
3089
3090 return ret;
3091}
3092
Eric Andersen044228d2001-07-17 01:12:36 +00003093static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003094{
3095 struct obj_section *sec;
3096 ElfW(Addr) base = f->baseaddr;
3097
3098 for (sec = f->load_order; sec; sec = sec->load_next) {
3099 char *secimg;
3100
Eric Andersen2bf658d2001-02-24 20:01:53 +00003101 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003102 continue;
3103
3104 secimg = image + (sec->header.sh_addr - base);
3105
3106 /* Note that we allocated data for NOBITS sections earlier. */
3107 memcpy(secimg, sec->contents, sec->header.sh_size);
3108 }
3109
3110 return 1;
3111}
3112
3113/*======================================================================*/
3114
Eric Andersen044228d2001-07-17 01:12:36 +00003115static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003116{
3117 struct obj_file *f;
3118 ElfW(Shdr) * section_headers;
3119 int shnum, i;
3120 char *shstrtab;
3121
3122 /* Read the file header. */
3123
3124 f = arch_new_file();
3125 memset(f, 0, sizeof(*f));
3126 f->symbol_cmp = strcmp;
3127 f->symbol_hash = obj_elf_hash;
3128 f->load_order_search_start = &f->load_order;
3129
3130 fseek(fp, 0, SEEK_SET);
3131 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003132 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003133 return NULL;
3134 }
3135
3136 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003137 || f->header.e_ident[EI_MAG1] != ELFMAG1
3138 || f->header.e_ident[EI_MAG2] != ELFMAG2
3139 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003140 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003141 return NULL;
3142 }
3143 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003144 || f->header.e_ident[EI_DATA] != ELFDATAM
3145 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3146 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003147 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003148 return NULL;
3149 }
3150 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003151 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003152 return NULL;
3153 }
3154
3155 /* Read the section headers. */
3156
3157 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003158 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003159 (unsigned long) f->header.e_shentsize,
3160 (unsigned long) sizeof(ElfW(Shdr)));
3161 return NULL;
3162 }
3163
3164 shnum = f->header.e_shnum;
3165 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3166 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3167
3168 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3169 fseek(fp, f->header.e_shoff, SEEK_SET);
3170 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003171 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003172 return NULL;
3173 }
3174
3175 /* Read the section data. */
3176
3177 for (i = 0; i < shnum; ++i) {
3178 struct obj_section *sec;
3179
3180 f->sections[i] = sec = arch_new_section();
3181 memset(sec, 0, sizeof(*sec));
3182
3183 sec->header = section_headers[i];
3184 sec->idx = i;
3185
Eric Andersen2bf658d2001-02-24 20:01:53 +00003186 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003187 case SHT_NULL:
3188 case SHT_NOTE:
3189 case SHT_NOBITS:
3190 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003191 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003192
3193 case SHT_PROGBITS:
3194#if LOADBITS
3195 if (!loadprogbits) {
3196 sec->contents = NULL;
3197 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003198 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003199#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003200 case SHT_SYMTAB:
3201 case SHT_STRTAB:
3202 case SHT_RELM:
3203 if (sec->header.sh_size > 0) {
3204 sec->contents = xmalloc(sec->header.sh_size);
3205 fseek(fp, sec->header.sh_offset, SEEK_SET);
3206 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3207 bb_perror_msg("error reading ELF section data");
3208 return NULL;
3209 }
3210 } else {
3211 sec->contents = NULL;
3212 }
3213 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003214
3215#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003216 case SHT_RELA:
3217 bb_error_msg("RELA relocations not supported on this architecture");
3218 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003219#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003220 case SHT_REL:
3221 bb_error_msg("REL relocations not supported on this architecture");
3222 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003223#endif
3224
Eric Andersen3b1a7442003-12-24 20:30:45 +00003225 default:
3226 if (sec->header.sh_type >= SHT_LOPROC) {
3227 /* Assume processor specific section types are debug
3228 info and can safely be ignored. If this is ever not
3229 the case (Hello MIPS?), don't put ifdefs here but
3230 create an arch_load_proc_section(). */
3231 break;
3232 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003233
Eric Andersen3b1a7442003-12-24 20:30:45 +00003234 bb_error_msg("can't handle sections of type %ld",
3235 (long) sec->header.sh_type);
3236 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003237 }
3238 }
3239
3240 /* Do what sort of interpretation as needed by each section. */
3241
3242 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3243
3244 for (i = 0; i < shnum; ++i) {
3245 struct obj_section *sec = f->sections[i];
3246 sec->name = shstrtab + sec->header.sh_name;
3247 }
3248
3249 for (i = 0; i < shnum; ++i) {
3250 struct obj_section *sec = f->sections[i];
3251
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003252 /* .modinfo should be contents only but gcc has no attribute for that.
3253 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3254 */
3255 if (strcmp(sec->name, ".modinfo") == 0)
3256 sec->header.sh_flags &= ~SHF_ALLOC;
3257
Eric Andersen9f16d612000-06-12 23:11:16 +00003258 if (sec->header.sh_flags & SHF_ALLOC)
3259 obj_insert_section_load_order(f, sec);
3260
3261 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003262 case SHT_SYMTAB:
3263 {
3264 unsigned long nsym, j;
3265 char *strtab;
3266 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003267
Eric Andersen3b1a7442003-12-24 20:30:45 +00003268 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3269 bb_error_msg("symbol size mismatch: %lu != %lu",
3270 (unsigned long) sec->header.sh_entsize,
3271 (unsigned long) sizeof(ElfW(Sym)));
3272 return NULL;
3273 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003274
Eric Andersen3b1a7442003-12-24 20:30:45 +00003275 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3276 strtab = f->sections[sec->header.sh_link]->contents;
3277 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003278
Eric Andersen3b1a7442003-12-24 20:30:45 +00003279 /* Allocate space for a table of local symbols. */
3280 j = f->local_symtab_size = sec->header.sh_info;
3281 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003282
Eric Andersen3b1a7442003-12-24 20:30:45 +00003283 /* Insert all symbols into the hash table. */
3284 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3285 ElfW(Addr) val = sym->st_value;
3286 const char *name;
3287 if (sym->st_name)
3288 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003289 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003290 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003291 else
3292 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003293
Eric Andersenbf833552003-08-13 19:56:33 +00003294#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003295 /*
3296 * For sh64 it is possible that the target of a branch
3297 * requires a mode switch (32 to 16 and back again).
3298 *
3299 * This is implied by the lsb being set in the target
3300 * address for SHmedia mode and clear for SHcompact.
3301 */
3302 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003303#endif
3304
Eric Andersen3b1a7442003-12-24 20:30:45 +00003305 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3306 val, sym->st_size);
3307 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003308 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003309 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003310
Eric Andersen3b1a7442003-12-24 20:30:45 +00003311 case SHT_RELM:
3312 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3313 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3314 (unsigned long) sec->header.sh_entsize,
3315 (unsigned long) sizeof(ElfW(RelM)));
3316 return NULL;
3317 }
3318 break;
3319 /* XXX Relocation code from modutils-2.3.19 is not here.
3320 * Why? That's about 20 lines of code from obj/obj_load.c,
3321 * which gets done in a second pass through the sections.
3322 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003323 }
3324 }
3325
3326 return f;
3327}
3328
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003329#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003330/*
3331 * load the unloaded sections directly into the memory allocated by
3332 * kernel for the module
3333 */
3334
Eric Andersenac5dbd12001-08-22 05:26:08 +00003335static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003336{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003337 ElfW(Addr) base = f->baseaddr;
3338 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003339
Eric Andersen8ae319a2001-05-21 16:09:18 +00003340 for (sec = f->load_order; sec; sec = sec->load_next) {
3341
3342 /* section already loaded? */
3343 if (sec->contents != NULL)
3344 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003345
Eric Andersen8ae319a2001-05-21 16:09:18 +00003346 if (sec->header.sh_size == 0)
3347 continue;
3348
3349 sec->contents = imagebase + (sec->header.sh_addr - base);
3350 fseek(fp, sec->header.sh_offset, SEEK_SET);
3351 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003352 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003353 return 0;
3354 }
3355
3356 }
3357 return 1;
3358}
3359#endif
3360
Eric Andersen9f16d612000-06-12 23:11:16 +00003361static void hide_special_symbols(struct obj_file *f)
3362{
3363 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003364 SPFX "cleanup_module",
3365 SPFX "init_module",
3366 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003367 NULL
3368 };
3369
3370 struct obj_symbol *sym;
3371 const char *const *p;
3372
3373 for (p = specials; *p; ++p)
3374 if ((sym = obj_find_symbol(f, *p)) != NULL)
3375 sym->info =
3376 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3377}
3378
Glenn L McGrath759515c2003-08-30 06:00:33 +00003379
Eric Andersen71ae64b2002-10-10 04:20:21 +00003380#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003381static int obj_gpl_license(struct obj_file *f, const char **license)
3382{
3383 struct obj_section *sec;
3384 /* This list must match *exactly* the list of allowable licenses in
3385 * linux/include/linux/module.h. Checking for leading "GPL" will not
3386 * work, somebody will use "GPL sucks, this is proprietary".
3387 */
3388 static const char *gpl_licenses[] = {
3389 "GPL",
3390 "GPL v2",
3391 "GPL and additional rights",
3392 "Dual BSD/GPL",
3393 "Dual MPL/GPL",
3394 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003395
Eric Andersen166fa462002-09-16 05:30:24 +00003396 if ((sec = obj_find_section(f, ".modinfo"))) {
3397 const char *value, *ptr, *endptr;
3398 ptr = sec->contents;
3399 endptr = ptr + sec->header.sh_size;
3400 while (ptr < endptr) {
3401 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3402 int i;
3403 if (license)
3404 *license = value+1;
3405 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3406 if (strcmp(value+1, gpl_licenses[i]) == 0)
3407 return(0);
3408 }
3409 return(2);
3410 }
3411 if (strchr(ptr, '\0'))
3412 ptr = strchr(ptr, '\0') + 1;
3413 else
3414 ptr = endptr;
3415 }
3416 }
3417 return(1);
3418}
3419
3420#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3421#define TAINT_PROPRIETORY_MODULE (1<<0)
3422#define TAINT_FORCED_MODULE (1<<1)
3423#define TAINT_UNSAFE_SMP (1<<2)
3424#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3425
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003426static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003427 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3428{
3429 char buf[80];
3430 int oldval;
3431 static int first = 1;
3432 if (fd < 0 && !kernel_has_tainted)
3433 return; /* New modutils on old kernel */
3434 printf("Warning: loading %s will taint the kernel: %s%s\n",
3435 m_name, text1, text2);
3436 if (first) {
3437 printf(" See %s for information about tainted modules\n", TAINT_URL);
3438 first = 0;
3439 }
3440 if (fd >= 0) {
3441 read(fd, buf, sizeof(buf)-1);
3442 buf[sizeof(buf)-1] = '\0';
3443 oldval = strtoul(buf, NULL, 10);
3444 sprintf(buf, "%d\n", oldval | taint);
3445 write(fd, buf, strlen(buf));
3446 }
3447}
3448
3449/* Check if loading this module will taint the kernel. */
3450static void check_tainted_module(struct obj_file *f, char *m_name)
3451{
3452 static const char tainted_file[] = TAINT_FILENAME;
3453 int fd, kernel_has_tainted;
3454 const char *ptr;
3455
3456 kernel_has_tainted = 1;
3457 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3458 if (errno == ENOENT)
3459 kernel_has_tainted = 0;
3460 else if (errno == EACCES)
3461 kernel_has_tainted = 1;
3462 else {
3463 perror(tainted_file);
3464 kernel_has_tainted = 0;
3465 }
3466 }
3467
3468 switch (obj_gpl_license(f, &ptr)) {
3469 case 0:
3470 break;
3471 case 1:
3472 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3473 break;
3474 case 2:
3475 /* The module has a non-GPL license so we pretend that the
3476 * kernel always has a taint flag to get a warning even on
3477 * kernels without the proc flag.
3478 */
3479 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3480 break;
3481 default:
3482 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3483 break;
3484 }
3485
3486 if (flag_force_load)
3487 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3488
3489 if (fd >= 0)
3490 close(fd);
3491}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003492#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3493#define check_tainted_module(x, y) do { } while(0);
3494#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003495
Eric Andersen889dd202003-01-23 04:48:34 +00003496#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3497/* add module source, timestamp, kernel version and a symbol for the
3498 * start of some sections. this info is used by ksymoops to do better
3499 * debugging.
3500 */
3501static int
3502get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3503{
3504#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003505 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003506#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003507 strncpy(str, "???", sizeof(str));
3508 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003509#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3510}
3511
3512/* add module source, timestamp, kernel version and a symbol for the
3513 * start of some sections. this info is used by ksymoops to do better
3514 * debugging.
3515 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003516static void
Eric Andersen889dd202003-01-23 04:48:34 +00003517add_ksymoops_symbols(struct obj_file *f, const char *filename,
3518 const char *m_name)
3519{
3520 static const char symprefix[] = "__insmod_";
3521 struct obj_section *sec;
3522 struct obj_symbol *sym;
3523 char *name, *absolute_filename;
3524 char str[STRVERSIONLEN], real[PATH_MAX];
3525 int i, l, lm_name, lfilename, use_ksymtab, version;
3526 struct stat statbuf;
3527
3528 static const char *section_names[] = {
3529 ".text",
3530 ".rodata",
3531 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003532 ".bss",
3533 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003534 };
3535
3536 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003537 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003538 }
3539 else {
3540 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003541 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003542 errno = save_errno;
3543 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003544 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003545 }
3546
3547 lm_name = strlen(m_name);
3548 lfilename = strlen(absolute_filename);
3549
3550 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3551 * are not to be exported. otherwise leave ksymtab alone for now, the
3552 * "export all symbols" compatibility code will export these symbols later.
3553 */
3554 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3555
3556 if ((sec = obj_find_section(f, ".this"))) {
3557 /* tag the module header with the object name, last modified
3558 * timestamp and module version. worst case for module version
3559 * is 0xffffff, decimal 16777215. putting all three fields in
3560 * one symbol is less readable but saves kernel space.
3561 */
3562 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003563 lm_name+ /* module name */
3564 2+ /* "_O" */
3565 lfilename+ /* object filename */
3566 2+ /* "_M" */
3567 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3568 2+ /* "_V" */
3569 8+ /* version in dec */
3570 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003571 name = xmalloc(l);
3572 if (stat(absolute_filename, &statbuf) != 0)
3573 statbuf.st_mtime = 0;
3574 version = get_module_version(f, str); /* -1 if not found */
3575 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003576 symprefix, m_name, absolute_filename,
3577 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3578 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003579 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003580 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3581 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003582 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003583 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003584 }
3585 free(absolute_filename);
3586#ifdef _NOT_SUPPORTED_
3587 /* record where the persistent data is going, same address as previous symbol */
3588
3589 if (f->persist) {
3590 l = sizeof(symprefix)+ /* "__insmod_" */
3591 lm_name+ /* module name */
3592 2+ /* "_P" */
3593 strlen(f->persist)+ /* data store */
3594 1; /* nul */
3595 name = xmalloc(l);
3596 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003597 symprefix, m_name, f->persist);
Eric Andersen889dd202003-01-23 04:48:34 +00003598 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003599 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003600 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003601 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003602 }
3603#endif /* _NOT_SUPPORTED_ */
3604 /* tag the desired sections if size is non-zero */
3605
3606 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3607 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003608 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003609 l = sizeof(symprefix)+ /* "__insmod_" */
3610 lm_name+ /* module name */
3611 2+ /* "_S" */
3612 strlen(sec->name)+ /* section name */
3613 2+ /* "_L" */
3614 8+ /* length in dec */
3615 1; /* nul */
3616 name = xmalloc(l);
3617 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003618 symprefix, m_name, sec->name,
3619 (long)sec->header.sh_size);
Eric Andersen889dd202003-01-23 04:48:34 +00003620 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003621 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003622 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003623 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003624 }
3625 }
3626}
3627#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3628
Eric Andersenbe65c352003-01-23 04:57:35 +00003629#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3630static void print_load_map(struct obj_file *f)
3631{
3632 struct obj_symbol *sym;
3633 struct obj_symbol **all, **p;
3634 struct obj_section *sec;
3635 int i, nsyms, *loaded;
3636
3637 /* Report on the section layout. */
3638
3639 printf("Sections: Size %-*s Align\n",
3640 (int) (2 * sizeof(void *)), "Address");
3641
3642 for (sec = f->load_order; sec; sec = sec->load_next) {
3643 int a;
3644 unsigned long tmp;
3645
3646 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3647 tmp >>= 1;
3648 if (a == -1)
3649 a = 0;
3650
3651 printf("%-15s %08lx %0*lx 2**%d\n",
3652 sec->name,
3653 (long)sec->header.sh_size,
3654 (int) (2 * sizeof(void *)),
3655 (long)sec->header.sh_addr,
3656 a);
3657 }
3658#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3659 /* Quick reference which section indicies are loaded. */
3660
3661 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3662 while (--i >= 0)
3663 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3664
3665 /* Collect the symbols we'll be listing. */
3666
3667 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3668 for (sym = f->symtab[i]; sym; sym = sym->next)
3669 if (sym->secidx <= SHN_HIRESERVE
3670 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3671 ++nsyms;
3672
3673 all = alloca(nsyms * sizeof(struct obj_symbol *));
3674
3675 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3676 for (sym = f->symtab[i]; sym; sym = sym->next)
3677 if (sym->secidx <= SHN_HIRESERVE
3678 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3679 *p++ = sym;
3680
3681 /* And list them. */
3682 printf("\nSymbols:\n");
3683 for (p = all; p < all + nsyms; ++p) {
3684 char type = '?';
3685 unsigned long value;
3686
3687 sym = *p;
3688 if (sym->secidx == SHN_ABS) {
3689 type = 'A';
3690 value = sym->value;
3691 } else if (sym->secidx == SHN_UNDEF) {
3692 type = 'U';
3693 value = 0;
3694 } else {
3695 sec = f->sections[sym->secidx];
3696
3697 if (sec->header.sh_type == SHT_NOBITS)
3698 type = 'B';
3699 else if (sec->header.sh_flags & SHF_ALLOC) {
3700 if (sec->header.sh_flags & SHF_EXECINSTR)
3701 type = 'T';
3702 else if (sec->header.sh_flags & SHF_WRITE)
3703 type = 'D';
3704 else
3705 type = 'R';
3706 }
3707 value = sym->value + sec->header.sh_addr;
3708 }
3709
3710 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
3711 type = tolower(type);
3712
3713 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3714 type, sym->name);
3715 }
3716#endif
3717}
3718
3719#endif
3720
Eric Andersen9f16d612000-06-12 23:11:16 +00003721extern int insmod_main( int argc, char **argv)
3722{
Eric Andersena18aaf12001-01-24 19:07:09 +00003723 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003724 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003725 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003726 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003727 unsigned long m_size;
3728 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003729 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003730 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003731 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003732 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003733 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003734#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003735 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003736 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003737 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003738#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003739#ifdef CONFIG_FEATURE_CLEAN_UP
3740 FILE *fp = 0;
3741#else
3742 FILE *fp;
3743#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003744#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3745 int flag_print_load_map = 0;
3746#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003747 int k_version = 0;
3748 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003749
Erik Andersene49d5ec2000-02-08 19:58:47 +00003750 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003751#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003752 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003753#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003754 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003755#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003756 {
3757 switch (opt) {
3758 case 'f': /* force loading */
3759 flag_force_load = 1;
3760 break;
3761 case 'k': /* module loaded by kerneld, auto-cleanable */
3762 flag_autoclean = 1;
3763 break;
3764 case 's': /* log to syslog */
3765 /* log to syslog -- not supported */
3766 /* but kernel needs this for request_module(), */
3767 /* as this calls: modprobe -k -s -- <module> */
3768 /* so silently ignore this flag */
3769 break;
3770 case 'v': /* verbose output */
3771 flag_verbose = 1;
3772 break;
3773 case 'q': /* silent */
3774 flag_quiet = 1;
3775 break;
3776 case 'x': /* do not export externs */
3777 flag_export = 0;
3778 break;
3779 case 'o': /* name the output module */
3780 free(m_name);
3781 m_name = bb_xstrdup(optarg);
3782 break;
3783 case 'L': /* Stub warning */
3784 /* This is needed for compatibility with modprobe.
3785 * In theory, this does locking, but we don't do
3786 * that. So be careful and plan your life around not
3787 * loading the same module 50 times concurrently. */
3788 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003789#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003790 case 'm': /* print module load map */
3791 flag_print_load_map = 1;
3792 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003793#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003794 default:
3795 bb_show_usage();
3796 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003797 }
Eric Andersen03d80912003-12-19 21:04:19 +00003798
Eric Andersena18aaf12001-01-24 19:07:09 +00003799 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003800 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003801 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003802
Erik Andersene49d5ec2000-02-08 19:58:47 +00003803 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003804 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003805 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003806 len = strlen(tmp);
3807
Eric Andersen03d80912003-12-19 21:04:19 +00003808 if (uname(&myuname) == 0) {
3809 if (myuname.release[0] == '2') {
3810 k_version = myuname.release[2] - '0';
3811 }
3812 }
3813
3814#if defined(CONFIG_FEATURE_2_6_MODULES)
3815 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003816 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003817 len-=3;
3818 tmp[len] = '\0';
3819 }
3820 else
3821#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003822 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3823 len-=2;
3824 tmp[len] = '\0';
3825 }
Eric Andersen2d342152002-06-18 05:16:25 +00003826
Eric Andersen03d80912003-12-19 21:04:19 +00003827
3828#if defined(CONFIG_FEATURE_2_6_MODULES)
3829 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00003830 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003831 else
Eric Andersen03d80912003-12-19 21:04:19 +00003832#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00003833 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003834
Eric Andersen61f83052002-06-22 17:15:42 +00003835 if (!m_name) {
3836 m_name = tmp;
3837 } else {
3838 free(tmp1);
3839 tmp1 = 0; /* flag for free(m_name) before exit() */
3840 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003841
Eric Andersen14d35432001-05-14 17:07:32 +00003842 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003843 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3844 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003845 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3846 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003847 if (k_version) { /* uname succeedd */
3848 char *module_dir;
3849 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003850 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003851
Eric Andersen03d80912003-12-19 21:04:19 +00003852 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003853 /* Jump through hoops in case /lib/modules/`uname -r`
3854 * is a symlink. We do not want recursive_action to
3855 * follow symlinks, but we do want to follow the
3856 * /lib/modules/`uname -r` dir, So resolve it ourselves
3857 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00003858 if (realpath (tmdn, real_module_dir) == NULL)
3859 module_dir = tmdn;
3860 else
3861 module_dir = real_module_dir;
3862 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003863 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00003864 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00003865 }
3866
3867 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00003868 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003869 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003870 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003871
Eric Andersen03d80912003-12-19 21:04:19 +00003872 free(m_filename);
3873 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003874 if (realpath (_PATH_MODULES, module_dir) == NULL)
3875 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003876 /* No module found under /lib/modules/`uname -r`, this
3877 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00003878 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00003879 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00003880 {
Eric Andersen61f83052002-06-22 17:15:42 +00003881 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00003882 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00003883 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003884 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00003885 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00003886 }
3887 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003888 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00003889 }
Eric Andersen03d80912003-12-19 21:04:19 +00003890 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003891 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00003892
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00003893 if (!flag_quiet)
3894 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003895
Eric Andersene7047882003-12-11 01:42:13 +00003896#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003897 if (k_version > 4)
3898 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003899 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00003900 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003901 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00003902 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003903#endif
3904
Eric Andersen8ae319a2001-05-21 16:09:18 +00003905 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003906 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003907
Eric Andersen9f16d612000-06-12 23:11:16 +00003908 if (get_modinfo_value(f, "kernel_version") == NULL)
3909 m_has_modinfo = 0;
3910 else
3911 m_has_modinfo = 1;
3912
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003913#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003914 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00003915 if (!flag_quiet) {
3916 if (uname(&uts_info) < 0)
3917 uts_info.release[0] = '\0';
3918 if (m_has_modinfo) {
3919 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00003920 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003921 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00003922 "compiled for");
3923 goto out;
3924 }
3925 }
3926
3927 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
3928 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003929 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003930 "\t%s was compiled for kernel version %s\n"
3931 "\twhile this kernel is version %s",
3932 m_filename, m_strversion, uts_info.release);
3933 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003934 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003935 "\t%s was compiled for kernel version %s\n"
3936 "\twhile this kernel is version %s.",
3937 m_filename, m_strversion, uts_info.release);
3938 goto out;
3939 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003940 }
3941 }
3942 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003943#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003944
Eric Andersencb3b9b12004-06-22 11:50:52 +00003945 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003946 if (!new_get_kernel_symbols())
3947 goto out;
3948 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00003949 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003950 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003951 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00003952 }
3953
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003954#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003955 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00003956 if (m_has_modinfo)
3957 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003958
3959 if (m_crcs != k_crcs)
3960 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003961#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003962
Erik Andersene49d5ec2000-02-08 19:58:47 +00003963 /* Let the module know about the kernel symbols. */
3964 add_kernel_symbols(f);
3965
Eric Andersen9f16d612000-06-12 23:11:16 +00003966 /* Allocate common symbols, symbol tables, and string tables. */
3967
Eric Andersencb3b9b12004-06-22 11:50:52 +00003968 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003969 {
3970 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003971 }
3972
Eric Andersen9f16d612000-06-12 23:11:16 +00003973 if (!obj_check_undefineds(f)) {
3974 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003975 }
3976 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00003977 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003978
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003979 /* done with the module name, on to the optional var=value arguments */
3980 ++optind;
3981
Eric Andersen9f16d612000-06-12 23:11:16 +00003982 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00003983 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00003984 {
3985 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003986 }
3987 }
3988
Eric Andersen9f16d612000-06-12 23:11:16 +00003989 arch_create_got(f);
3990 hide_special_symbols(f);
3991
Eric Andersen889dd202003-01-23 04:48:34 +00003992#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3993 add_ksymoops_symbols(f, m_filename, m_name);
3994#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3995
Eric Andersencb3b9b12004-06-22 11:50:52 +00003996 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003997
Erik Andersene49d5ec2000-02-08 19:58:47 +00003998 /* Find current size of the module */
3999 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004000
4001
Erik Andersene49d5ec2000-02-08 19:58:47 +00004002 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004003 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004004 case EEXIST:
4005 bb_error_msg("A module named %s already exists", m_name);
4006 goto out;
4007 case ENOMEM:
4008 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4009 m_size);
4010 goto out;
4011 default:
4012 bb_perror_msg("create_module: %s", m_name);
4013 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004014 }
Erik Andersend387d011999-12-21 02:55:11 +00004015
Eric Andersen8ae319a2001-05-21 16:09:18 +00004016#if !LOADBITS
4017 /*
4018 * the PROGBITS section was not loaded by the obj_load
4019 * now we can load them directly into the kernel memory
4020 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004021 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004022 delete_module(m_name);
4023 goto out;
4024 }
Eric Andersen03d80912003-12-19 21:04:19 +00004025#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004026
Eric Andersen9f16d612000-06-12 23:11:16 +00004027 if (!obj_relocate(f, m_addr)) {
4028 delete_module(m_name);
4029 goto out;
4030 }
Erik Andersend387d011999-12-21 02:55:11 +00004031
Eric Andersencb3b9b12004-06-22 11:50:52 +00004032 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004033 {
4034 delete_module(m_name);
4035 goto out;
4036 }
4037
Eric Andersenbe65c352003-01-23 04:57:35 +00004038#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4039 if(flag_print_load_map)
4040 print_load_map(f);
4041#endif
4042
Matt Kraai3e856ce2000-12-01 02:55:13 +00004043 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004044
4045out:
Eric Andersen61f83052002-06-22 17:15:42 +00004046#ifdef CONFIG_FEATURE_CLEAN_UP
4047 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004048 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004049 if(tmp1) {
4050 free(tmp1);
4051 } else {
4052 free(m_name);
4053 }
4054 free(m_filename);
4055#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004056 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004057}
Eric Andersene7047882003-12-11 01:42:13 +00004058
4059
4060#endif
4061
4062
4063#ifdef CONFIG_FEATURE_2_6_MODULES
4064
4065#include <sys/mman.h>
4066#include <asm/unistd.h>
4067#include <sys/syscall.h>
4068
4069/* We use error numbers in a loose translation... */
4070static const char *moderror(int err)
4071{
4072 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004073 case ENOEXEC:
4074 return "Invalid module format";
4075 case ENOENT:
4076 return "Unknown symbol in module";
4077 case ESRCH:
4078 return "Module has wrong symbol version";
4079 case EINVAL:
4080 return "Invalid parameters";
4081 default:
4082 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004083 }
4084}
4085
4086extern int insmod_ng_main( int argc, char **argv)
4087{
4088 int i;
4089 int fd;
4090 long int ret;
4091 struct stat st;
4092 unsigned long len;
4093 void *map;
4094 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004095
Eric Andersene7047882003-12-11 01:42:13 +00004096 filename = argv[1];
4097 if (!filename) {
4098 bb_show_usage();
4099 return -1;
4100 }
4101
4102 /* Rest is options */
4103 for (i = 2; i < argc; i++) {
4104 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4105 /* Spaces handled by "" pairs, but no way of escaping quotes */
4106 if (strchr(argv[i], ' ')) {
4107 strcat(options, "\"");
4108 strcat(options, argv[i]);
4109 strcat(options, "\"");
4110 } else {
4111 strcat(options, argv[i]);
4112 }
4113 strcat(options, " ");
4114 }
4115
4116 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4117 bb_perror_msg_and_die("cannot open module `%s'", filename);
4118 }
4119
4120 fstat(fd, &st);
4121 len = st.st_size;
4122 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4123 if (map == MAP_FAILED) {
4124 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4125 }
4126
4127 ret = syscall(__NR_init_module, map, len, options);
4128 if (ret != 0) {
4129 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004130 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004131 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004132
Eric Andersene7047882003-12-11 01:42:13 +00004133 return 0;
4134}
4135
4136#endif