blob: f38daa257cc24e0e8837f022d08427e9c5989d17 [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 *
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +000058 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Erik Andersen02104321999-12-17 18:57:34 +000059 */
60
Erik Andersen02104321999-12-17 18:57:34 +000061#include <stdlib.h>
62#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000064#include <errno.h>
65#include <unistd.h>
66#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000067#include <ctype.h>
68#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000069#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000070#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000071#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000072#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000073#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000074
Eric Andersene7047882003-12-11 01:42:13 +000075#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
Eric Andersene7047882003-12-11 01:42:13 +000076 !defined(CONFIG_FEATURE_2_6_MODULES)
77#define CONFIG_FEATURE_2_4_MODULES
78#endif
79
Eric Andersencb3b9b12004-06-22 11:50:52 +000080#if !defined(CONFIG_FEATURE_2_4_MODULES)
Eric Andersene7047882003-12-11 01:42:13 +000081#define insmod_ng_main insmod_main
82#endif
83
Eric Andersene7047882003-12-11 01:42:13 +000084#if defined(CONFIG_FEATURE_2_6_MODULES)
85extern int insmod_ng_main( int argc, char **argv);
86#endif
87
Eric Andersencb3b9b12004-06-22 11:50:52 +000088
89#if defined(CONFIG_FEATURE_2_4_MODULES)
90
Eric Andersen64c8b172001-04-05 07:33:10 +000091
Eric Andersenbdfd0d72001-10-24 05:00:29 +000092#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000093#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000094#else
95#define LOADBITS 1
96#endif
97
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098
Mike Frysinger63654c12004-12-26 09:13:32 +000099/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000100#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +0000101#define MATCH_MACHINE(x) (x == EM_ALPHA)
102#define SHT_RELM SHT_RELA
103#define Elf64_RelM Elf64_Rela
104#define ELFCLASSM ELFCLASS64
105#endif
106
Eric Andersen45a05132004-09-02 23:03:25 +0000107/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000108#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +0000109#define MATCH_MACHINE(x) (x == EM_ARM)
110#define SHT_RELM SHT_REL
111#define Elf32_RelM Elf32_Rel
112#define ELFCLASSM ELFCLASS32
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000113#define CONFIG_USE_PLT_ENTRIES
114#define CONFIG_PLT_ENTRY_SIZE 8
115#define CONFIG_USE_GOT_ENTRIES
116#define CONFIG_GOT_ENTRY_SIZE 8
117#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000118#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000119
Eric Andersen45a05132004-09-02 23:03:25 +0000120/* CRIS */
121#if defined(__cris__)
122#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000123#define SHT_RELM SHT_RELA
124#define Elf32_RelM Elf32_Rela
125#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000126#ifndef EM_CRIS
127#define EM_CRIS 76
128#define R_CRIS_NONE 0
129#define R_CRIS_32 3
130#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000131#endif
132
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000133/* H8/300 */
134#if defined(__H8300H__) || defined(__H8300S__)
135#define MATCH_MACHINE(x) (x == EM_H8_300)
136#define SHT_RELM SHT_RELA
137#define Elf32_RelM Elf32_Rela
138#define ELFCLASSM ELFCLASS32
139#define CONFIG_USE_SINGLE
140#define SYMBOL_PREFIX "_"
141#endif
142
Mike Frysinger63654c12004-12-26 09:13:32 +0000143/* PA-RISC / HP-PA */
144#if defined(__hppa__)
145#define MATCH_MACHINE(x) (x == EM_PARISC)
146#define SHT_RELM SHT_RELA
147#if defined(__LP64__)
148#define Elf64_RelM Elf64_Rela
149#define ELFCLASSM ELFCLASS64
150#else
151#define Elf32_RelM Elf32_Rela
152#define ELFCLASSM ELFCLASS32
153#endif
154#endif
155
Eric Andersen45a05132004-09-02 23:03:25 +0000156/* x86 */
157#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000158#ifndef EM_486
159#define MATCH_MACHINE(x) (x == EM_386)
160#else
161#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
162#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000163#define SHT_RELM SHT_REL
164#define Elf32_RelM Elf32_Rel
165#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000166#define CONFIG_USE_GOT_ENTRIES
167#define CONFIG_GOT_ENTRY_SIZE 4
168#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000169#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000170
Eric Andersen45a05132004-09-02 23:03:25 +0000171/* IA64, aka Itanium */
172#if defined(__ia64__)
173#define MATCH_MACHINE(x) (x == EM_IA_64)
174#define SHT_RELM SHT_RELA
175#define Elf64_RelM Elf64_Rela
176#define ELFCLASSM ELFCLASS64
177#endif
178
179/* m68k */
180#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000181#define MATCH_MACHINE(x) (x == EM_68K)
182#define SHT_RELM SHT_RELA
183#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000184#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000185#define CONFIG_USE_GOT_ENTRIES
186#define CONFIG_GOT_ENTRY_SIZE 4
187#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000188#endif
189
Eric Andersen45a05132004-09-02 23:03:25 +0000190/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000191#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000192#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
193#define SHT_RELM SHT_REL
194#define Elf32_RelM Elf32_Rel
195#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000196/* Account for ELF spec changes. */
197#ifndef EM_MIPS_RS3_LE
198#ifdef EM_MIPS_RS4_BE
199#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
200#else
201#define EM_MIPS_RS3_LE 10
202#endif
203#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000204#define ARCHDATAM "__dbe_table"
205#endif
206
Mike Frysingerf982d862006-01-04 00:11:26 +0000207/* Nios II */
208#if defined(__nios2__)
209#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
210#define SHT_RELM SHT_RELA
211#define Elf32_RelM Elf32_Rela
212#define ELFCLASSM ELFCLASS32
213#endif
214
Eric Andersen45a05132004-09-02 23:03:25 +0000215/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000216#if defined(__powerpc64__)
217#define MATCH_MACHINE(x) (x == EM_PPC64)
218#define SHT_RELM SHT_RELA
219#define Elf64_RelM Elf64_Rela
220#define ELFCLASSM ELFCLASS64
221#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000222#define MATCH_MACHINE(x) (x == EM_PPC)
223#define SHT_RELM SHT_RELA
224#define Elf32_RelM Elf32_Rela
225#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000226#define CONFIG_USE_PLT_ENTRIES
227#define CONFIG_PLT_ENTRY_SIZE 16
228#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000229#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000230#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000231#define ARCHDATAM "__ftr_fixup"
232#endif
233
Eric Andersen45a05132004-09-02 23:03:25 +0000234/* S390 */
235#if defined(__s390__)
236#define MATCH_MACHINE(x) (x == EM_S390)
237#define SHT_RELM SHT_RELA
238#define Elf32_RelM Elf32_Rela
239#define ELFCLASSM ELFCLASS32
240#define CONFIG_USE_PLT_ENTRIES
241#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000242#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000243#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000244#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000245#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000246
Eric Andersen45a05132004-09-02 23:03:25 +0000247/* SuperH */
248#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000249#define MATCH_MACHINE(x) (x == EM_SH)
250#define SHT_RELM SHT_RELA
251#define Elf32_RelM Elf32_Rela
252#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000253#define CONFIG_USE_GOT_ENTRIES
254#define CONFIG_GOT_ENTRY_SIZE 4
255#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000256/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000257/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000258#if defined(__sh__) && BB_BIG_ENDIAN
259# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000260#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000261/* it may or may not work on the SH1/SH2... Error on those also */
262#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000263#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000264#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000265#endif
266
Eric Andersen45a05132004-09-02 23:03:25 +0000267/* Sparc */
268#if defined(__sparc__)
269#define MATCH_MACHINE(x) (x == EM_SPARC)
270#define SHT_RELM SHT_RELA
271#define Elf32_RelM Elf32_Rela
272#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000273#endif
274
Eric Andersen45a05132004-09-02 23:03:25 +0000275/* v850e */
276#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000277#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
278#define SHT_RELM SHT_RELA
279#define Elf32_RelM Elf32_Rela
280#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000281#define CONFIG_USE_PLT_ENTRIES
282#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000283#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000284#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000285#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000286#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000287#define SYMBOL_PREFIX "_"
288#endif
289
Eric Andersen45a05132004-09-02 23:03:25 +0000290/* X86_64 */
291#if defined(__x86_64__)
292#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000293#define SHT_RELM SHT_RELA
Mike Frysinger91fbdac2005-10-02 06:44:39 +0000294#define CONFIG_USE_GOT_ENTRIES
295#define CONFIG_GOT_ENTRY_SIZE 8
296#define CONFIG_USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000297#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000298#define ELFCLASSM ELFCLASS64
299#endif
300
Eric Andersencffd5022002-05-24 06:50:15 +0000301#ifndef SHT_RELM
302#error Sorry, but insmod.c does not yet support this architecture...
303#endif
304
305
Eric Andersen9f16d612000-06-12 23:11:16 +0000306//----------------------------------------------------------------------------
307//--------modutils module.h, lines 45-242
308//----------------------------------------------------------------------------
309
310/* Definitions for the Linux module syscall interface.
311 Copyright 1996, 1997 Linux International.
312
313 Contributed by Richard Henderson <rth@tamu.edu>
314
315 This file is part of the Linux modutils.
316
317 This program is free software; you can redistribute it and/or modify it
318 under the terms of the GNU General Public License as published by the
319 Free Software Foundation; either version 2 of the License, or (at your
320 option) any later version.
321
322 This program is distributed in the hope that it will be useful, but
323 WITHOUT ANY WARRANTY; without even the implied warranty of
324 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
325 General Public License for more details.
326
327 You should have received a copy of the GNU General Public License
328 along with this program; if not, write to the Free Software Foundation,
329 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
330
331
332#ifndef MODUTILS_MODULE_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000333/* Why? static const int MODUTILS_MODULE_H = 1;*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000334
Mike Frysinger63654c12004-12-26 09:13:32 +0000335#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000336
337/*======================================================================*/
338/* For sizeof() which are related to the module platform and not to the
339 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
340
341#define tgt_sizeof_char sizeof(char)
342#define tgt_sizeof_short sizeof(short)
343#define tgt_sizeof_int sizeof(int)
344#define tgt_sizeof_long sizeof(long)
345#define tgt_sizeof_char_p sizeof(char *)
346#define tgt_sizeof_void_p sizeof(void *)
347#define tgt_long long
348
349#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
350#undef tgt_sizeof_long
351#undef tgt_sizeof_char_p
352#undef tgt_sizeof_void_p
353#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000354enum {
355 tgt_sizeof_long = 8,
356 tgt_sizeof_char_p = 8,
357 tgt_sizeof_void_p = 8
358};
Eric Andersen9f16d612000-06-12 23:11:16 +0000359#define tgt_long long long
360#endif
361
362/*======================================================================*/
363/* The structures used in Linux 2.1. */
364
365/* Note: new_module_symbol does not use tgt_long intentionally */
366struct new_module_symbol
367{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000368 unsigned long value;
369 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000370};
371
372struct new_module_persist;
373
374struct new_module_ref
375{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000376 unsigned tgt_long dep; /* kernel addresses */
377 unsigned tgt_long ref;
378 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000379};
380
381struct new_module
382{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000383 unsigned tgt_long size_of_struct; /* == sizeof(module) */
384 unsigned tgt_long next;
385 unsigned tgt_long name;
386 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000387
Eric Andersen3b1a7442003-12-24 20:30:45 +0000388 tgt_long usecount;
389 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000390
Eric Andersen3b1a7442003-12-24 20:30:45 +0000391 unsigned nsyms;
392 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000393
Eric Andersen3b1a7442003-12-24 20:30:45 +0000394 unsigned tgt_long syms;
395 unsigned tgt_long deps;
396 unsigned tgt_long refs;
397 unsigned tgt_long init;
398 unsigned tgt_long cleanup;
399 unsigned tgt_long ex_table_start;
400 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000401#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000402 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000403#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000404 /* Everything after here is extension. */
405 unsigned tgt_long persist_start;
406 unsigned tgt_long persist_end;
407 unsigned tgt_long can_unload;
408 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000409 const char *kallsyms_start; /* All symbols for kernel debugging */
410 const char *kallsyms_end;
411 const char *archdata_start; /* arch specific data for module */
412 const char *archdata_end;
413 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000414};
415
Eric Andersencffd5022002-05-24 06:50:15 +0000416#ifdef ARCHDATAM
417#define ARCHDATA_SEC_NAME ARCHDATAM
418#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000419#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000420#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000421#define KALLSYMS_SEC_NAME "__kallsyms"
422
423
Eric Andersen9f16d612000-06-12 23:11:16 +0000424struct new_module_info
425{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000426 unsigned long addr;
427 unsigned long size;
428 unsigned long flags;
429 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000430};
431
432/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000433enum {
434 NEW_MOD_RUNNING = 1,
435 NEW_MOD_DELETED = 2,
436 NEW_MOD_AUTOCLEAN = 4,
437 NEW_MOD_VISITED = 8,
438 NEW_MOD_USED_ONCE = 16
439};
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersencb3b9b12004-06-22 11:50:52 +0000441int init_module(const char *name, const struct new_module *);
442int query_module(const char *name, int which, void *buf,
443 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000444
445/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000446enum {
447 QM_MODULES = 1,
448 QM_DEPS = 2,
449 QM_REFS = 3,
450 QM_SYMBOLS = 4,
451 QM_INFO = 5
452};
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
Rob Landleybc68cd12006-03-10 19:22:06 +0000496/* Why? static 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
Eric Andersen9f16d612000-06-12 23:11:16 +0000506#ifndef ElfW
507# if ELFCLASSM == ELFCLASS32
508# define ElfW(x) Elf32_ ## x
509# define ELFW(x) ELF32_ ## x
510# else
511# define ElfW(x) Elf64_ ## x
512# define ELFW(x) ELF64_ ## x
513# endif
514#endif
515
Eric Andersen85e5e722003-07-22 08:56:55 +0000516/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000517#ifndef ELF32_ST_INFO
518# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
519#endif
520
521#ifndef ELF64_ST_INFO
522# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
523#endif
524
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000525#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
526#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
527#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
528#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
529#define ELF_R_SYM(val) ELFW(R_SYM)(val)
530
Eric Andersen9f16d612000-06-12 23:11:16 +0000531struct 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);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000671#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000672static int obj_gpl_license(struct obj_file *f, const char **license);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000673#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
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
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000684#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000685#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"
Rob Landleybc68cd12006-03-10 19:22:06 +0000689enum { 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;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000729 ElfW(Addr) *addr;
730 ElfW(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,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +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 Andersen3496fdc2006-01-30 23:09:20 +0000849#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000850#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000851 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000852#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000853#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000854#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000855 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000856 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000857# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000858 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000859# else
Eric Andersencffd5022002-05-24 06:50:15 +0000860 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000861# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000862#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000863
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000864 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000865
Eric Andersencffd5022002-05-24 06:50:15 +0000866#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000867
Eric Andersen3b1a7442003-12-24 20:30:45 +0000868 case R_ARM_NONE:
869 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000870
Eric Andersen3b1a7442003-12-24 20:30:45 +0000871 case R_ARM_ABS32:
872 *loc += v;
873 break;
Miles Baderae28b042002-04-01 09:34:25 +0000874
Eric Andersen3b1a7442003-12-24 20:30:45 +0000875 case R_ARM_GOT32:
876 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000879 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
880 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000881 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000882
Eric Andersen3496fdc2006-01-30 23:09:20 +0000883 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 *loc += got - dot;
885 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_PC24:
888 case R_ARM_PLT32:
889 goto bb_use_plt;
890
891 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3496fdc2006-01-30 23:09:20 +0000892 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000893 *loc += v - got;
894 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000895
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000896#elif defined(__cris__)
897
898 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000899 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000900
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000901 case R_CRIS_32:
902 /* CRIS keeps the relocation value in the r_addend field and
903 * should not use whats in *loc at all
904 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000905 *loc = v;
906 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000907
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000908#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000909
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000910 case R_H8_DIR24R8:
911 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
912 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000913 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000914 case R_H8_DIR24A8:
915 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000916 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000917 case R_H8_DIR32:
918 case R_H8_DIR32A16:
919 *loc += v;
920 break;
921 case R_H8_PCREL16:
922 v -= dot + 2;
923 if ((ElfW(Sword))v > 0x7fff ||
924 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
925 ret = obj_reloc_overflow;
926 else
927 *(unsigned short *)loc = v;
928 break;
929 case R_H8_PCREL8:
930 v -= dot + 1;
931 if ((ElfW(Sword))v > 0x7f ||
932 (ElfW(Sword))v < -(ElfW(Sword))0x80)
933 ret = obj_reloc_overflow;
934 else
935 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000936 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000937
Eric Andersencffd5022002-05-24 06:50:15 +0000938#elif defined(__i386__)
939
Eric Andersen3b1a7442003-12-24 20:30:45 +0000940 case R_386_NONE:
941 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000942
Eric Andersen3b1a7442003-12-24 20:30:45 +0000943 case R_386_32:
944 *loc += v;
945 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000946
Eric Andersen3b1a7442003-12-24 20:30:45 +0000947 case R_386_PLT32:
948 case R_386_PC32:
949 *loc += v - dot;
950 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000951
Eric Andersen3b1a7442003-12-24 20:30:45 +0000952 case R_386_GLOB_DAT:
953 case R_386_JMP_SLOT:
954 *loc = v;
955 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000956
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 case R_386_RELATIVE:
958 *loc += f->baseaddr;
959 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000960
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 case R_386_GOTPC:
962 assert(got != 0);
963 *loc += got - dot;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GOT32:
967 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_GOTOFF:
970 assert(got != 0);
971 *loc += v - got;
972 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
974#elif defined(__mc68000__)
975
Eric Andersen3b1a7442003-12-24 20:30:45 +0000976 case R_68K_NONE:
977 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000978
Eric Andersen3b1a7442003-12-24 20:30:45 +0000979 case R_68K_32:
980 *loc += v;
981 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000982
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 case R_68K_8:
984 if (v > 0xff) {
985 ret = obj_reloc_overflow;
986 }
987 *(char *)loc = v;
988 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000989
Eric Andersen3b1a7442003-12-24 20:30:45 +0000990 case R_68K_16:
991 if (v > 0xffff) {
992 ret = obj_reloc_overflow;
993 }
994 *(short *)loc = v;
995 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000996
Eric Andersen3b1a7442003-12-24 20:30:45 +0000997 case R_68K_PC8:
998 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000999 if ((ElfW(Sword))v > 0x7f ||
1000 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001001 ret = obj_reloc_overflow;
1002 }
1003 *(char *)loc = v;
1004 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001005
Eric Andersen3b1a7442003-12-24 20:30:45 +00001006 case R_68K_PC16:
1007 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001008 if ((ElfW(Sword))v > 0x7fff ||
1009 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001010 ret = obj_reloc_overflow;
1011 }
1012 *(short *)loc = v;
1013 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001014
Eric Andersen3b1a7442003-12-24 20:30:45 +00001015 case R_68K_PC32:
1016 *(int *)loc = v - dot;
1017 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001018
Eric Andersen3b1a7442003-12-24 20:30:45 +00001019 case R_68K_GLOB_DAT:
1020 case R_68K_JMP_SLOT:
1021 *loc = v;
1022 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001023
Eric Andersen3b1a7442003-12-24 20:30:45 +00001024 case R_68K_RELATIVE:
1025 *(int *)loc += f->baseaddr;
1026 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001027
Eric Andersen3b1a7442003-12-24 20:30:45 +00001028 case R_68K_GOT32:
1029 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001030
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001031# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001032 case R_68K_GOTOFF:
1033 assert(got != 0);
1034 *loc += v - got;
1035 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001036# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001037
1038#elif defined(__mips__)
1039
Eric Andersen3b1a7442003-12-24 20:30:45 +00001040 case R_MIPS_NONE:
1041 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001042
Eric Andersen3b1a7442003-12-24 20:30:45 +00001043 case R_MIPS_32:
1044 *loc += v;
1045 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001046
Eric Andersen3b1a7442003-12-24 20:30:45 +00001047 case R_MIPS_26:
1048 if (v % 4)
1049 ret = obj_reloc_dangerous;
1050 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1051 ret = obj_reloc_overflow;
1052 *loc =
1053 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1054 0x03ffffff);
1055 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001056
Eric Andersen3b1a7442003-12-24 20:30:45 +00001057 case R_MIPS_HI16:
1058 {
1059 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001060
Eric Andersen3b1a7442003-12-24 20:30:45 +00001061 /* We cannot relocate this one now because we don't know the value
1062 of the carry we need to add. Save the information, and let LO16
1063 do the actual relocation. */
1064 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1065 n->addr = loc;
1066 n->value = v;
1067 n->next = ifile->mips_hi16_list;
1068 ifile->mips_hi16_list = n;
1069 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001070 }
1071
Eric Andersen3b1a7442003-12-24 20:30:45 +00001072 case R_MIPS_LO16:
1073 {
1074 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001075 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001076
1077 /* Sign extend the addend we extract from the lo insn. */
1078 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1079
1080 if (ifile->mips_hi16_list != NULL) {
1081 struct mips_hi16 *l;
1082
1083 l = ifile->mips_hi16_list;
1084 while (l != NULL) {
1085 struct mips_hi16 *next;
1086 unsigned long insn;
1087
1088 /* The value for the HI16 had best be the same. */
1089 assert(v == l->value);
1090
1091 /* Do the HI16 relocation. Note that we actually don't
1092 need to know anything about the LO16 itself, except where
1093 to find the low 16 bits of the addend needed by the LO16. */
1094 insn = *l->addr;
1095 val =
1096 ((insn & 0xffff) << 16) +
1097 vallo;
1098 val += v;
1099
1100 /* Account for the sign extension that will happen in the
1101 low bits. */
1102 val =
1103 ((val >> 16) +
1104 ((val & 0x8000) !=
1105 0)) & 0xffff;
1106
1107 insn = (insn & ~0xffff) | val;
1108 *l->addr = insn;
1109
1110 next = l->next;
1111 free(l);
1112 l = next;
1113 }
1114
1115 ifile->mips_hi16_list = NULL;
1116 }
1117
1118 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1119 val = v + vallo;
1120 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1121 *loc = insnlo;
1122 break;
1123 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001124
Mike Frysingerf982d862006-01-04 00:11:26 +00001125#elif defined(__nios2__)
1126
1127 case R_NIOS2_NONE:
1128 break;
1129
1130 case R_NIOS2_BFD_RELOC_32:
1131 *loc += v;
1132 break;
1133
1134 case R_NIOS2_BFD_RELOC_16:
1135 if (v > 0xffff) {
1136 ret = obj_reloc_overflow;
1137 }
1138 *(short *)loc = v;
1139 break;
1140
1141 case R_NIOS2_BFD_RELOC_8:
1142 if (v > 0xff) {
1143 ret = obj_reloc_overflow;
1144 }
1145 *(char *)loc = v;
1146 break;
1147
1148 case R_NIOS2_S16:
1149 {
1150 Elf32_Addr word;
1151
1152 if ((Elf32_Sword)v > 0x7fff ||
1153 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1154 ret = obj_reloc_overflow;
1155 }
1156
1157 word = *loc;
1158 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1159 (word & 0x3f);
1160 }
1161 break;
1162
1163 case R_NIOS2_U16:
1164 {
1165 Elf32_Addr word;
1166
1167 if (v > 0xffff) {
1168 ret = obj_reloc_overflow;
1169 }
1170
1171 word = *loc;
1172 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1173 (word & 0x3f);
1174 }
1175 break;
1176
1177 case R_NIOS2_PCREL16:
1178 {
1179 Elf32_Addr word;
1180
1181 v -= dot + 4;
1182 if ((Elf32_Sword)v > 0x7fff ||
1183 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1184 ret = obj_reloc_overflow;
1185 }
1186
1187 word = *loc;
1188 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1189 }
1190 break;
1191
1192 case R_NIOS2_GPREL:
1193 {
1194 Elf32_Addr word, gp;
1195 /* get _gp */
1196 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1197 v-=gp;
1198 if ((Elf32_Sword)v > 0x7fff ||
1199 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1200 ret = obj_reloc_overflow;
1201 }
1202
1203 word = *loc;
1204 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1205 }
1206 break;
1207
1208 case R_NIOS2_CALL26:
1209 if (v & 3)
1210 ret = obj_reloc_dangerous;
1211 if ((v >> 28) != (dot >> 28))
1212 ret = obj_reloc_overflow;
1213 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1214 break;
1215
1216 case R_NIOS2_IMM5:
1217 {
1218 Elf32_Addr word;
1219
1220 if (v > 0x1f) {
1221 ret = obj_reloc_overflow;
1222 }
1223
1224 word = *loc & ~0x7c0;
1225 *loc = word | ((v & 0x1f) << 6);
1226 }
1227 break;
1228
1229 case R_NIOS2_IMM6:
1230 {
1231 Elf32_Addr word;
1232
1233 if (v > 0x3f) {
1234 ret = obj_reloc_overflow;
1235 }
1236
1237 word = *loc & ~0xfc0;
1238 *loc = word | ((v & 0x3f) << 6);
1239 }
1240 break;
1241
1242 case R_NIOS2_IMM8:
1243 {
1244 Elf32_Addr word;
1245
1246 if (v > 0xff) {
1247 ret = obj_reloc_overflow;
1248 }
1249
1250 word = *loc & ~0x3fc0;
1251 *loc = word | ((v & 0xff) << 6);
1252 }
1253 break;
1254
1255 case R_NIOS2_HI16:
1256 {
1257 Elf32_Addr word;
1258
1259 word = *loc;
1260 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1261 (word & 0x3f);
1262 }
1263 break;
1264
1265 case R_NIOS2_LO16:
1266 {
1267 Elf32_Addr word;
1268
1269 word = *loc;
1270 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1271 (word & 0x3f);
1272 }
1273 break;
1274
1275 case R_NIOS2_HIADJ16:
1276 {
1277 Elf32_Addr word1, word2;
1278
1279 word1 = *loc;
1280 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1281 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1282 (word1 & 0x3f);
1283 }
1284 break;
1285
Mike Frysingerebee0e72006-02-18 06:14:31 +00001286#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001287 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001288
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001289#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001290
Eric Andersen3b1a7442003-12-24 20:30:45 +00001291 case R_PPC_ADDR16_HA:
1292 *(unsigned short *)loc = (v + 0x8000) >> 16;
1293 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001294
Eric Andersen3b1a7442003-12-24 20:30:45 +00001295 case R_PPC_ADDR16_HI:
1296 *(unsigned short *)loc = v >> 16;
1297 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001298
Eric Andersen3b1a7442003-12-24 20:30:45 +00001299 case R_PPC_ADDR16_LO:
1300 *(unsigned short *)loc = v;
1301 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001302
Eric Andersen3b1a7442003-12-24 20:30:45 +00001303 case R_PPC_REL24:
1304 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001305
Eric Andersen3b1a7442003-12-24 20:30:45 +00001306 case R_PPC_REL32:
1307 *loc = v - dot;
1308 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001309
Eric Andersen3b1a7442003-12-24 20:30:45 +00001310 case R_PPC_ADDR32:
1311 *loc = v;
1312 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001313
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001314#elif defined(__s390__)
1315
1316 case R_390_32:
1317 *(unsigned int *) loc += v;
1318 break;
1319 case R_390_16:
1320 *(unsigned short *) loc += v;
1321 break;
1322 case R_390_8:
1323 *(unsigned char *) loc += v;
1324 break;
1325
1326 case R_390_PC32:
1327 *(unsigned int *) loc += v - dot;
1328 break;
1329 case R_390_PC16DBL:
1330 *(unsigned short *) loc += (v - dot) >> 1;
1331 break;
1332 case R_390_PC16:
1333 *(unsigned short *) loc += v - dot;
1334 break;
1335
1336 case R_390_PLT32:
1337 case R_390_PLT16DBL:
1338 /* find the plt entry and initialize it. */
1339 assert(isym != NULL);
1340 pe = (struct arch_single_entry *) &isym->pltent;
1341 assert(pe->allocated);
1342 if (pe->inited == 0) {
1343 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1344 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1345 ip[1] = 0x100607f1;
1346 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1347 ip[2] = v - 2;
1348 else
1349 ip[2] = v;
1350 pe->inited = 1;
1351 }
1352
1353 /* Insert relative distance to target. */
1354 v = plt + pe->offset - dot;
1355 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1356 *(unsigned int *) loc = (unsigned int) v;
1357 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1358 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1359 break;
1360
1361 case R_390_GLOB_DAT:
1362 case R_390_JMP_SLOT:
1363 *loc = v;
1364 break;
1365
1366 case R_390_RELATIVE:
1367 *loc += f->baseaddr;
1368 break;
1369
1370 case R_390_GOTPC:
1371 assert(got != 0);
1372 *(unsigned long *) loc += got - dot;
1373 break;
1374
1375 case R_390_GOT12:
1376 case R_390_GOT16:
1377 case R_390_GOT32:
1378 assert(isym != NULL);
1379 assert(got != 0);
1380 if (!isym->gotent.inited)
1381 {
1382 isym->gotent.inited = 1;
1383 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1384 }
1385 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1386 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1387 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1388 *(unsigned short *) loc += isym->gotent.offset;
1389 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1390 *(unsigned int *) loc += isym->gotent.offset;
1391 break;
1392
1393# ifndef R_390_GOTOFF32
1394# define R_390_GOTOFF32 R_390_GOTOFF
1395# endif
1396 case R_390_GOTOFF32:
1397 assert(got != 0);
1398 *loc += v - got;
1399 break;
1400
Eric Andersencffd5022002-05-24 06:50:15 +00001401#elif defined(__sh__)
1402
Eric Andersen3b1a7442003-12-24 20:30:45 +00001403 case R_SH_NONE:
1404 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001405
Eric Andersen3b1a7442003-12-24 20:30:45 +00001406 case R_SH_DIR32:
1407 *loc += v;
1408 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001409
Eric Andersen3b1a7442003-12-24 20:30:45 +00001410 case R_SH_REL32:
1411 *loc += v - dot;
1412 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001413
Eric Andersen3b1a7442003-12-24 20:30:45 +00001414 case R_SH_PLT32:
1415 *loc = v - dot;
1416 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001417
Eric Andersen3b1a7442003-12-24 20:30:45 +00001418 case R_SH_GLOB_DAT:
1419 case R_SH_JMP_SLOT:
1420 *loc = v;
1421 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001422
Eric Andersen3b1a7442003-12-24 20:30:45 +00001423 case R_SH_RELATIVE:
1424 *loc = f->baseaddr + rel->r_addend;
1425 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001426
Eric Andersen3b1a7442003-12-24 20:30:45 +00001427 case R_SH_GOTPC:
1428 assert(got != 0);
1429 *loc = got - dot + rel->r_addend;
1430 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001431
Eric Andersen3b1a7442003-12-24 20:30:45 +00001432 case R_SH_GOT32:
1433 goto bb_use_got;
1434
1435 case R_SH_GOTOFF:
1436 assert(got != 0);
1437 *loc = v - got;
1438 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001439
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001440# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001441 case R_SH_IMM_MEDLOW16:
1442 case R_SH_IMM_LOW16:
1443 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001444 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001445
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001446 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001447 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001448
Eric Andersen3b1a7442003-12-24 20:30:45 +00001449 /*
1450 * movi and shori have the format:
1451 *
1452 * | op | imm | reg | reserved |
1453 * 31..26 25..10 9.. 4 3 .. 0
1454 *
1455 * so we simply mask and or in imm.
1456 */
1457 word = *loc & ~0x3fffc00;
1458 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001459
Eric Andersen3b1a7442003-12-24 20:30:45 +00001460 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001461
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 break;
1463 }
Eric Andersenbf833552003-08-13 19:56:33 +00001464
Eric Andersen3b1a7442003-12-24 20:30:45 +00001465 case R_SH_IMM_MEDLOW16_PCREL:
1466 case R_SH_IMM_LOW16_PCREL:
1467 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001468 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001469
Eric Andersen3b1a7442003-12-24 20:30:45 +00001470 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001471
Eric Andersen3b1a7442003-12-24 20:30:45 +00001472 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001473
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001474 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001476
Eric Andersen3b1a7442003-12-24 20:30:45 +00001477 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001480
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 break;
1482 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001483# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001484
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001485#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001486
Eric Andersen3b1a7442003-12-24 20:30:45 +00001487 case R_V850_NONE:
1488 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 case R_V850_32:
1491 /* We write two shorts instead of a long because even
1492 32-bit insns only need half-word alignment, but
1493 32-bit data needs to be long-word aligned. */
1494 v += ((unsigned short *)loc)[0];
1495 v += ((unsigned short *)loc)[1] << 16;
1496 ((unsigned short *)loc)[0] = v & 0xffff;
1497 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1498 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001499
Eric Andersen3b1a7442003-12-24 20:30:45 +00001500 case R_V850_22_PCREL:
1501 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001502
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001503#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001504
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001505 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001507
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001508 case R_X86_64_64:
1509 *loc += v;
1510 break;
1511
1512 case R_X86_64_32:
1513 *(unsigned int *) loc += v;
1514 if (v > 0xffffffff)
1515 {
1516 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1517 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1518 }
1519 break;
1520
1521 case R_X86_64_32S:
1522 *(signed int *) loc += v;
1523 break;
1524
1525 case R_X86_64_16:
1526 *(unsigned short *) loc += v;
1527 break;
1528
1529 case R_X86_64_8:
1530 *(unsigned char *) loc += v;
1531 break;
1532
1533 case R_X86_64_PC32:
1534 *(unsigned int *) loc += v - dot;
1535 break;
1536
1537 case R_X86_64_PC16:
1538 *(unsigned short *) loc += v - dot;
1539 break;
1540
1541 case R_X86_64_PC8:
1542 *(unsigned char *) loc += v - dot;
1543 break;
1544
1545 case R_X86_64_GLOB_DAT:
1546 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001547 *loc = v;
1548 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001549
1550 case R_X86_64_RELATIVE:
1551 *loc += f->baseaddr;
1552 break;
1553
1554 case R_X86_64_GOT32:
1555 case R_X86_64_GOTPCREL:
1556 goto bb_use_got;
1557# if 0
1558 assert(isym != NULL);
1559 if (!isym->gotent.reloc_done)
1560 {
1561 isym->gotent.reloc_done = 1;
1562 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1563 }
1564 /* XXX are these really correct? */
1565 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1566 *(unsigned int *) loc += v + isym->gotent.offset;
1567 else
1568 *loc += isym->gotent.offset;
1569 break;
1570# endif
1571
Mike Frysingerf982d862006-01-04 00:11:26 +00001572#else
1573# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001574#endif
1575
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001576 default:
1577 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1578 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001579 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001580
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001581#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001582
Eric Andersen3b1a7442003-12-24 20:30:45 +00001583bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001584
Eric Andersen3b1a7442003-12-24 20:30:45 +00001585 /* find the plt entry and initialize it if necessary */
1586 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001587
Eric Andersencffd5022002-05-24 06:50:15 +00001588#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001589 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1590 pe = pe->next;
1591 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001592#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001593 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001594#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001595
Eric Andersen3b1a7442003-12-24 20:30:45 +00001596 if (! pe->inited) {
1597 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001598
Eric Andersen3b1a7442003-12-24 20:30:45 +00001599 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001600
1601#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001602 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1603 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001604#endif
1605#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001606 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001607 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001608 ip[2] = 0x7d6903a6; /* mtctr r11 */
1609 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001610#endif
Miles Baderae28b042002-04-01 09:34:25 +00001611#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001612 /* We have to trash a register, so we assume that any control
1613 transfer more than 21-bits away must be a function call
1614 (so we can use a call-clobbered register). */
1615 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1616 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001617#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001618 pe->inited = 1;
1619 }
Eric Andersen21adca72000-12-06 18:18:26 +00001620
Eric Andersen3b1a7442003-12-24 20:30:45 +00001621 /* relative distance to target */
1622 v -= dot;
1623 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001624#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001625 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001626#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001627 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001628#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001629 /* go via the plt */
1630 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001631
1632#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001634#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001635 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001636#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001637 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001638
Eric Andersen3b1a7442003-12-24 20:30:45 +00001639 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001640#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001641 /* Convert to words. */
1642 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001643
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001645#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001646#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001648#endif
Miles Baderae28b042002-04-01 09:34:25 +00001649#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 /* We write two shorts instead of a long because even 32-bit insns
1651 only need half-word alignment, but the 32-bit data write needs
1652 to be long-word aligned. */
1653 ((unsigned short *)loc)[0] =
1654 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1655 | ((v >> 16) & 0x3f); /* offs high part */
1656 ((unsigned short *)loc)[1] =
1657 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001658#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001660#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001661
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001662#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001664
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 assert(isym != NULL);
1666 /* needs an entry in the .got: set it, once */
1667 if (!isym->gotent.inited) {
1668 isym->gotent.inited = 1;
1669 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1670 }
1671 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001672#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001673 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001674#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001676#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001677 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001678
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001679#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001680 }
1681
1682 return ret;
1683}
1684
Eric Andersencffd5022002-05-24 06:50:15 +00001685
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001686#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001687
1688static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1689 int offset, int size)
1690{
1691 struct arch_list_entry *pe;
1692
1693 for (pe = *list; pe != NULL; pe = pe->next) {
1694 if (pe->addend == rel->r_addend) {
1695 break;
1696 }
1697 }
1698
1699 if (pe == NULL) {
1700 pe = xmalloc(sizeof(struct arch_list_entry));
1701 pe->next = *list;
1702 pe->addend = rel->r_addend;
1703 pe->offset = offset;
1704 pe->inited = 0;
1705 *list = pe;
1706 return size;
1707 }
1708 return 0;
1709}
1710
1711#endif
1712
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001713#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001714
1715static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1716 int offset, int size)
1717{
1718 if (single->allocated == 0) {
1719 single->allocated = 1;
1720 single->offset = offset;
1721 single->inited = 0;
1722 return size;
1723 }
1724 return 0;
1725}
1726
1727#endif
1728
1729#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1730
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001731static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001732 int offset, int size)
1733{
1734 struct obj_section *myrelsec = obj_find_section(f, name);
1735
1736 if (offset == 0) {
1737 offset += size;
1738 }
1739
1740 if (myrelsec) {
1741 obj_extend_section(myrelsec, offset);
1742 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001743 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001744 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001745 assert(myrelsec);
1746 }
1747
1748 return myrelsec;
1749}
1750
1751#endif
1752
1753static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001754{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001755#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001756 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001757 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001758#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001759 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001760#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001761#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001762 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001763#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001764 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001765 ElfW(RelM) *rel, *relend;
1766 ElfW(Sym) *symtab, *extsym;
1767 const char *strtab, *name;
1768 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001769
Eric Andersen21adca72000-12-06 18:18:26 +00001770 for (i = 0; i < f->header.e_shnum; ++i) {
1771 relsec = f->sections[i];
1772 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001773 continue;
1774
Eric Andersen21adca72000-12-06 18:18:26 +00001775 symsec = f->sections[relsec->header.sh_link];
1776 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001777
Eric Andersen21adca72000-12-06 18:18:26 +00001778 rel = (ElfW(RelM) *) relsec->contents;
1779 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1780 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001781 strtab = (const char *) strsec->contents;
1782
1783 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001784 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001785
Eric Andersencffd5022002-05-24 06:50:15 +00001786#if defined(CONFIG_USE_GOT_ENTRIES)
1787 got_allocate = 0;
1788#endif
1789#if defined(CONFIG_USE_PLT_ENTRIES)
1790 plt_allocate = 0;
1791#endif
1792
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001793 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001794#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001795 case R_ARM_PC24:
1796 case R_ARM_PLT32:
1797 plt_allocate = 1;
1798 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001799
Eric Andersen3b1a7442003-12-24 20:30:45 +00001800 case R_ARM_GOTOFF:
1801 case R_ARM_GOTPC:
1802 got_needed = 1;
1803 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001804
Eric Andersen3b1a7442003-12-24 20:30:45 +00001805 case R_ARM_GOT32:
1806 got_allocate = 1;
1807 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001808
Eric Andersen21adca72000-12-06 18:18:26 +00001809#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001810 case R_386_GOTPC:
1811 case R_386_GOTOFF:
1812 got_needed = 1;
1813 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001814
Eric Andersen3b1a7442003-12-24 20:30:45 +00001815 case R_386_GOT32:
1816 got_allocate = 1;
1817 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001818
1819#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001820 case R_PPC_REL24:
1821 plt_allocate = 1;
1822 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001823
1824#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001825 case R_68K_GOT32:
1826 got_allocate = 1;
1827 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001828
Eric Andersen16451a02004-03-19 12:16:18 +00001829#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001830 case R_68K_GOTOFF:
1831 got_needed = 1;
1832 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001833#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001834
1835#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001836 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001837 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001838 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001839
Eric Andersen3b1a7442003-12-24 20:30:45 +00001840 case R_SH_GOTPC:
1841 case R_SH_GOTOFF:
1842 got_needed = 1;
1843 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001844
1845#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001846 case R_V850_22_PCREL:
1847 plt_needed = 1;
1848 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001849
1850#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001851 default:
1852 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001853 }
1854
Eric Andersen21adca72000-12-06 18:18:26 +00001855 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001856 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001857 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001858 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001859 }
1860 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001861#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001862 if (got_allocate) {
1863 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001864 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001865 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001866
1867 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001868 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001869#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001870#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001871 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001872#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001873 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001874 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001875 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001876#else
1877 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001878 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001879 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001880#endif
1881 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001882 }
1883#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001884 }
Miles Baderae28b042002-04-01 09:34:25 +00001885 }
Eric Andersen21adca72000-12-06 18:18:26 +00001886
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001887#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001888 if (got_needed) {
1889 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001890 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001891 }
Eric Andersen21adca72000-12-06 18:18:26 +00001892#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001893
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001894#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001895 if (plt_needed) {
1896 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001897 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001898 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001899#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001900
1901#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001902}
1903
Eric Andersen9f16d612000-06-12 23:11:16 +00001904/*======================================================================*/
1905
1906/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001907static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001908{
1909 unsigned long h = 0;
1910 unsigned long g;
1911 unsigned char ch;
1912
1913 while (n > 0) {
1914 ch = *name++;
1915 h = (h << 4) + ch;
1916 if ((g = (h & 0xf0000000)) != 0) {
1917 h ^= g >> 24;
1918 h &= ~g;
1919 }
1920 n--;
1921 }
1922 return h;
1923}
1924
Eric Andersen044228d2001-07-17 01:12:36 +00001925static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001926{
1927 return obj_elf_hash_n(name, strlen(name));
1928}
1929
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001930#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001931/* String comparison for non-co-versioned kernel and module. */
1932
1933static int ncv_strcmp(const char *a, const char *b)
1934{
1935 size_t alen = strlen(a), blen = strlen(b);
1936
1937 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1938 return strncmp(a, b, alen);
1939 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1940 return strncmp(a, b, blen);
1941 else
1942 return strcmp(a, b);
1943}
1944
1945/* String hashing for non-co-versioned kernel and module. Here
1946 we are simply forced to drop the crc from the hash. */
1947
1948static unsigned long ncv_symbol_hash(const char *str)
1949{
1950 size_t len = strlen(str);
1951 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1952 len -= 10;
1953 return obj_elf_hash_n(str, len);
1954}
1955
Eric Andersen044228d2001-07-17 01:12:36 +00001956static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001957obj_set_symbol_compare(struct obj_file *f,
1958 int (*cmp) (const char *, const char *),
1959 unsigned long (*hash) (const char *))
1960{
1961 if (cmp)
1962 f->symbol_cmp = cmp;
1963 if (hash) {
1964 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1965 int i;
1966
1967 f->symbol_hash = hash;
1968
1969 memcpy(tmptab, f->symtab, sizeof(tmptab));
1970 memset(f->symtab, 0, sizeof(f->symtab));
1971
1972 for (i = 0; i < HASH_BUCKETS; ++i)
1973 for (sym = tmptab[i]; sym; sym = next) {
1974 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1975 next = sym->next;
1976 sym->next = f->symtab[h];
1977 f->symtab[h] = sym;
1978 }
1979 }
1980}
1981
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001982#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001983
Eric Andersen044228d2001-07-17 01:12:36 +00001984static struct obj_symbol *
1985obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001986 unsigned long symidx, int info,
1987 int secidx, ElfW(Addr) value,
1988 unsigned long size)
1989{
1990 struct obj_symbol *sym;
1991 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001992 int n_type = ELF_ST_TYPE(info);
1993 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00001994
1995 for (sym = f->symtab[hash]; sym; sym = sym->next)
1996 if (f->symbol_cmp(sym->name, name) == 0) {
1997 int o_secidx = sym->secidx;
1998 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001999 int o_type = ELF_ST_TYPE(o_info);
2000 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002001
2002 /* A redefinition! Is it legal? */
2003
2004 if (secidx == SHN_UNDEF)
2005 return sym;
2006 else if (o_secidx == SHN_UNDEF)
2007 goto found;
2008 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2009 /* Cope with local and global symbols of the same name
2010 in the same object file, as might have been created
2011 by ld -r. The only reason locals are now seen at this
2012 level at all is so that we can do semi-sensible things
2013 with parameters. */
2014
2015 struct obj_symbol *nsym, **p;
2016
2017 nsym = arch_new_symbol();
2018 nsym->next = sym->next;
2019 nsym->ksymidx = -1;
2020
2021 /* Excise the old (local) symbol from the hash chain. */
2022 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2023 continue;
2024 *p = sym = nsym;
2025 goto found;
2026 } else if (n_binding == STB_LOCAL) {
2027 /* Another symbol of the same name has already been defined.
2028 Just add this to the local table. */
2029 sym = arch_new_symbol();
2030 sym->next = NULL;
2031 sym->ksymidx = -1;
2032 f->local_symtab[symidx] = sym;
2033 goto found;
2034 } else if (n_binding == STB_WEAK)
2035 return sym;
2036 else if (o_binding == STB_WEAK)
2037 goto found;
2038 /* Don't unify COMMON symbols with object types the programmer
2039 doesn't expect. */
2040 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002041 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002042 return sym;
2043 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002044 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002045 goto found;
2046 else {
2047 /* Don't report an error if the symbol is coming from
2048 the kernel or some external module. */
2049 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002050 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002051 return sym;
2052 }
2053 }
2054
2055 /* Completely new symbol. */
2056 sym = arch_new_symbol();
2057 sym->next = f->symtab[hash];
2058 f->symtab[hash] = sym;
2059 sym->ksymidx = -1;
2060
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002061 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002062 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002063 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002064 name, (long) symidx, (long) f->local_symtab_size);
2065 else
2066 f->local_symtab[symidx] = sym;
2067 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002068
Eric Andersen3b1a7442003-12-24 20:30:45 +00002069found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002070 sym->name = name;
2071 sym->value = value;
2072 sym->size = size;
2073 sym->secidx = secidx;
2074 sym->info = info;
2075
2076 return sym;
2077}
2078
Eric Andersen044228d2001-07-17 01:12:36 +00002079static struct obj_symbol *
2080obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002081{
2082 struct obj_symbol *sym;
2083 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2084
2085 for (sym = f->symtab[hash]; sym; sym = sym->next)
2086 if (f->symbol_cmp(sym->name, name) == 0)
2087 return sym;
2088
2089 return NULL;
2090}
2091
Eric Andersen044228d2001-07-17 01:12:36 +00002092static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002093 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2094{
2095 if (sym) {
2096 if (sym->secidx >= SHN_LORESERVE)
2097 return sym->value;
2098
2099 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2100 } else {
2101 /* As a special case, a NULL sym has value zero. */
2102 return 0;
2103 }
2104}
2105
Eric Andersen044228d2001-07-17 01:12:36 +00002106static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002107{
2108 int i, n = f->header.e_shnum;
2109
2110 for (i = 0; i < n; ++i)
2111 if (strcmp(f->sections[i]->name, name) == 0)
2112 return f->sections[i];
2113
2114 return NULL;
2115}
2116
2117static int obj_load_order_prio(struct obj_section *a)
2118{
2119 unsigned long af, ac;
2120
2121 af = a->header.sh_flags;
2122
2123 ac = 0;
2124 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002125 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002126 ac |= 32;
2127 if (af & SHF_ALLOC)
2128 ac |= 16;
2129 if (!(af & SHF_WRITE))
2130 ac |= 8;
2131 if (af & SHF_EXECINSTR)
2132 ac |= 4;
2133 if (a->header.sh_type != SHT_NOBITS)
2134 ac |= 2;
2135
2136 return ac;
2137}
2138
Eric Andersen044228d2001-07-17 01:12:36 +00002139static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002140obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2141{
2142 struct obj_section **p;
2143 int prio = obj_load_order_prio(sec);
2144 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2145 if (obj_load_order_prio(*p) < prio)
2146 break;
2147 sec->load_next = *p;
2148 *p = sec;
2149}
2150
Eric Andersen044228d2001-07-17 01:12:36 +00002151static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002152 const char *name,
2153 unsigned long align,
2154 unsigned long size)
2155{
2156 int newidx = f->header.e_shnum++;
2157 struct obj_section *sec;
2158
2159 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2160 f->sections[newidx] = sec = arch_new_section();
2161
2162 memset(sec, 0, sizeof(*sec));
2163 sec->header.sh_type = SHT_PROGBITS;
2164 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2165 sec->header.sh_size = size;
2166 sec->header.sh_addralign = align;
2167 sec->name = name;
2168 sec->idx = newidx;
2169 if (size)
2170 sec->contents = xmalloc(size);
2171
2172 obj_insert_section_load_order(f, sec);
2173
2174 return sec;
2175}
2176
Eric Andersen044228d2001-07-17 01:12:36 +00002177static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002178 const char *name,
2179 unsigned long align,
2180 unsigned long size)
2181{
2182 int newidx = f->header.e_shnum++;
2183 struct obj_section *sec;
2184
2185 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2186 f->sections[newidx] = sec = arch_new_section();
2187
2188 memset(sec, 0, sizeof(*sec));
2189 sec->header.sh_type = SHT_PROGBITS;
2190 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2191 sec->header.sh_size = size;
2192 sec->header.sh_addralign = align;
2193 sec->name = name;
2194 sec->idx = newidx;
2195 if (size)
2196 sec->contents = xmalloc(size);
2197
2198 sec->load_next = f->load_order;
2199 f->load_order = sec;
2200 if (f->load_order_search_start == &f->load_order)
2201 f->load_order_search_start = &sec->load_next;
2202
2203 return sec;
2204}
2205
Eric Andersen044228d2001-07-17 01:12:36 +00002206static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002207{
2208 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002209 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002210 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2211 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002212 return sec->contents + oldsize;
2213}
2214
2215
Eric Andersen9f16d612000-06-12 23:11:16 +00002216/* Conditionally add the symbols from the given symbol set to the
2217 new module. */
2218
2219static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002220add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002221 int idx, struct new_module_symbol *syms, size_t nsyms)
2222{
2223 struct new_module_symbol *s;
2224 size_t i;
2225 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002226#ifdef SYMBOL_PREFIX
2227 char *name_buf = 0;
2228 size_t name_alloced_size = 0;
2229#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002230#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2231 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002232
Glenn L McGrath759515c2003-08-30 06:00:33 +00002233 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002234#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002235 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002236 /* Only add symbols that are already marked external.
2237 If we override locals we may cause problems for
2238 argument initialization. We will also create a false
2239 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002240 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002241 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002242
Glenn L McGrath759515c2003-08-30 06:00:33 +00002243 /* GPL licensed modules can use symbols exported with
2244 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2245 * exported names. Non-GPL modules never see any GPLONLY_
2246 * symbols so they cannot fudge it by adding the prefix on
2247 * their references.
2248 */
2249 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002250#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002251 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002252 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002253 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002254#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002255 continue;
2256 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002257 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002258
Miles Baderae28b042002-04-01 09:34:25 +00002259#ifdef SYMBOL_PREFIX
2260 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2261 kernel exports `C names', but module object files
2262 reference `linker names'). */
2263 size_t extra = sizeof SYMBOL_PREFIX;
2264 size_t name_size = strlen (name) + extra;
2265 if (name_size > name_alloced_size) {
2266 name_alloced_size = name_size * 2;
2267 name_buf = alloca (name_alloced_size);
2268 }
2269 strcpy (name_buf, SYMBOL_PREFIX);
2270 strcpy (name_buf + extra - 1, name);
2271 name = name_buf;
2272#endif /* SYMBOL_PREFIX */
2273
2274 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002275 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002276#ifdef SYMBOL_PREFIX
2277 /* Put NAME_BUF into more permanent storage. */
2278 name = xmalloc (name_size);
2279 strcpy (name, name_buf);
2280#endif
2281 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002282 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002283 STT_NOTYPE),
2284 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002285 /* Did our symbol just get installed? If so, mark the
2286 module as "used". */
2287 if (sym->secidx == idx)
2288 used = 1;
2289 }
2290 }
2291
2292 return used;
2293}
2294
2295static void add_kernel_symbols(struct obj_file *f)
2296{
2297 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002298 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002299
2300 /* Add module symbols first. */
2301
2302 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2303 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002304 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2305 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002306
2307 n_ext_modules_used = nused;
2308
2309 /* And finally the symbols from the kernel proper. */
2310
2311 if (nksyms)
2312 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2313}
2314
2315static char *get_modinfo_value(struct obj_file *f, const char *key)
2316{
2317 struct obj_section *sec;
2318 char *p, *v, *n, *ep;
2319 size_t klen = strlen(key);
2320
2321 sec = obj_find_section(f, ".modinfo");
2322 if (sec == NULL)
2323 return NULL;
2324 p = sec->contents;
2325 ep = p + sec->header.sh_size;
2326 while (p < ep) {
2327 v = strchr(p, '=');
2328 n = strchr(p, '\0');
2329 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002330 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002331 return v + 1;
2332 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002333 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002334 return n;
2335 }
2336 p = n + 1;
2337 }
2338
2339 return NULL;
2340}
2341
2342
2343/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002344/* Functions relating to module loading after 2.1.18. */
2345
2346static int
2347new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2348{
2349 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002350 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002351 struct obj_symbol *sym;
2352 char *contents, *loc;
2353 int min, max, n;
2354
2355 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002356 if ((q = strchr(p, '=')) == NULL) {
2357 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002358 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002359 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002360
2361 key = alloca(q - p + 6);
2362 memcpy(key, "parm_", 5);
2363 memcpy(key + 5, p, q - p);
2364 key[q - p + 5] = 0;
2365
2366 p = get_modinfo_value(f, key);
2367 key += 5;
2368 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002369 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002370 return 0;
2371 }
2372
Miles Baderae28b042002-04-01 09:34:25 +00002373#ifdef SYMBOL_PREFIX
2374 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2375 strcpy (sym_name, SYMBOL_PREFIX);
2376 strcat (sym_name, key);
2377#else
2378 sym_name = key;
2379#endif
2380 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002381
2382 /* Also check that the parameter was not resolved from the kernel. */
2383 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002384 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002385 return 0;
2386 }
2387
2388 if (isdigit(*p)) {
2389 min = strtoul(p, &p, 10);
2390 if (*p == '-')
2391 max = strtoul(p + 1, &p, 10);
2392 else
2393 max = min;
2394 } else
2395 min = max = 1;
2396
2397 contents = f->sections[sym->secidx]->contents;
2398 loc = contents + sym->value;
2399 n = (*++q != '\0');
2400
2401 while (1) {
2402 if ((*p == 's') || (*p == 'c')) {
2403 char *str;
2404
2405 /* Do C quoting if we begin with a ", else slurp the lot. */
2406 if (*q == '"') {
2407 char *r;
2408
2409 str = alloca(strlen(q));
2410 for (r = str, q++; *q != '"'; ++q, ++r) {
2411 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002412 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002413 key);
2414 return 0;
2415 } else if (*q == '\\')
2416 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002417 case 'a':
2418 *r = '\a';
2419 break;
2420 case 'b':
2421 *r = '\b';
2422 break;
2423 case 'e':
2424 *r = '\033';
2425 break;
2426 case 'f':
2427 *r = '\f';
2428 break;
2429 case 'n':
2430 *r = '\n';
2431 break;
2432 case 'r':
2433 *r = '\r';
2434 break;
2435 case 't':
2436 *r = '\t';
2437 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002438
Eric Andersen3b1a7442003-12-24 20:30:45 +00002439 case '0':
2440 case '1':
2441 case '2':
2442 case '3':
2443 case '4':
2444 case '5':
2445 case '6':
2446 case '7':
2447 {
2448 int c = *q - '0';
2449 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002450 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002451 if (q[1] >= '0' && q[1] <= '7')
2452 c = (c * 8) + *++q - '0';
2453 }
2454 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002455 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002456 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002457
Eric Andersen3b1a7442003-12-24 20:30:45 +00002458 default:
2459 *r = *q;
2460 break;
2461 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002462 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002463 }
2464 *r = '\0';
2465 ++q;
2466 } else {
2467 char *r;
2468
2469 /* In this case, the string is not quoted. We will break
2470 it using the coma (like for ints). If the user wants to
2471 include comas in a string, he just has to quote it */
2472
2473 /* Search the next coma */
2474 r = strchr(q, ',');
2475
2476 /* Found ? */
2477 if (r != (char *) NULL) {
2478 /* Recopy the current field */
2479 str = alloca(r - q + 1);
2480 memcpy(str, q, r - q);
2481
Eric Andersenaff114c2004-04-14 17:51:38 +00002482 /* I don't know if it is useful, as the previous case
2483 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002484 str[r - q] = '\0';
2485
2486 /* Keep next fields */
2487 q = r;
2488 } else {
2489 /* last string */
2490 str = q;
2491 q = "";
2492 }
2493 }
2494
2495 if (*p == 's') {
2496 /* Normal string */
2497 obj_string_patch(f, sym->secidx, loc - contents, str);
2498 loc += tgt_sizeof_char_p;
2499 } else {
2500 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002501 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002502
2503 /* Get the size of each member */
2504 /* Probably we should do that outside the loop ? */
2505 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002506 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002507 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002508 return 0;
2509 }
2510 charssize = strtoul(p + 1, (char **) NULL, 10);
2511
2512 /* Check length */
2513 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002514 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002515 charssize - 1);
2516 return 0;
2517 }
2518
2519 /* Copy to location */
2520 strcpy((char *) loc, str);
2521 loc += charssize;
2522 }
2523 } else {
2524 long v = strtoul(q, &q, 0);
2525 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002526 case 'b':
2527 *loc++ = v;
2528 break;
2529 case 'h':
2530 *(short *) loc = v;
2531 loc += tgt_sizeof_short;
2532 break;
2533 case 'i':
2534 *(int *) loc = v;
2535 loc += tgt_sizeof_int;
2536 break;
2537 case 'l':
2538 *(long *) loc = v;
2539 loc += tgt_sizeof_long;
2540 break;
2541
2542 default:
2543 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2544 return 0;
2545 }
2546 }
2547
2548retry_end_of_value:
2549 switch (*q) {
2550 case '\0':
2551 goto end_of_arg;
2552
2553 case ' ':
2554 case '\t':
2555 case '\n':
2556 case '\r':
2557 ++q;
2558 goto retry_end_of_value;
2559
2560 case ',':
2561 if (++n > max) {
2562 bb_error_msg("too many values for %s (max %d)", key, max);
2563 return 0;
2564 }
2565 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002566 break;
2567
2568 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002569 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002570 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002571 }
2572 }
2573
Eric Andersen3b1a7442003-12-24 20:30:45 +00002574end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002575 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002576 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002577 return 0;
2578 }
2579
2580 argc--, argv++;
2581 }
2582
2583 return 1;
2584}
2585
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002586#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002587static int new_is_module_checksummed(struct obj_file *f)
2588{
2589 const char *p = get_modinfo_value(f, "using_checksums");
2590 if (p)
2591 return atoi(p);
2592 else
2593 return 0;
2594}
2595
2596/* Get the module's kernel version in the canonical integer form. */
2597
2598static int
2599new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2600{
2601 char *p, *q;
2602 int a, b, c;
2603
2604 p = get_modinfo_value(f, "kernel_version");
2605 if (p == NULL)
2606 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002607 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002608
2609 a = strtoul(p, &p, 10);
2610 if (*p != '.')
2611 return -1;
2612 b = strtoul(p + 1, &p, 10);
2613 if (*p != '.')
2614 return -1;
2615 c = strtoul(p + 1, &q, 10);
2616 if (p + 1 == q)
2617 return -1;
2618
2619 return a << 16 | b << 8 | c;
2620}
2621
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002622#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002623
2624
Eric Andersen9f16d612000-06-12 23:11:16 +00002625/* Fetch the loaded modules, and all currently exported symbols. */
2626
2627static int new_get_kernel_symbols(void)
2628{
2629 char *module_names, *mn;
2630 struct external_module *modules, *m;
2631 struct new_module_symbol *syms, *s;
2632 size_t ret, bufsize, nmod, nsyms, i, j;
2633
2634 /* Collect the loaded modules. */
2635
2636 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002637retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002638 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002639 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002640 module_names = xrealloc(module_names, bufsize = ret);
2641 goto retry_modules_load;
2642 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002643 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002644 return 0;
2645 }
2646
2647 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002648
2649 /* Collect the modules' symbols. */
2650
Mark Whitley94fd4802001-03-12 23:08:34 +00002651 if (nmod){
2652 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2653 memset(modules, 0, nmod * sizeof(*modules));
2654 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002655 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002656 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002657
Mark Whitley94fd4802001-03-12 23:08:34 +00002658 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2659 if (errno == ENOENT) {
2660 /* The module was removed out from underneath us. */
2661 continue;
2662 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002663 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002664 return 0;
2665 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002666
Mark Whitley94fd4802001-03-12 23:08:34 +00002667 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002668retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002669 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2670 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002671 case ENOSPC:
2672 syms = xrealloc(syms, bufsize = ret);
2673 goto retry_mod_sym_load;
2674 case ENOENT:
2675 /* The module was removed out from underneath us. */
2676 continue;
2677 default:
2678 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2679 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002680 }
2681 }
2682 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002683
Mark Whitley94fd4802001-03-12 23:08:34 +00002684 m->name = mn;
2685 m->addr = info.addr;
2686 m->nsyms = nsyms;
2687 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002688
Mark Whitley94fd4802001-03-12 23:08:34 +00002689 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2690 s->name += (unsigned long) syms;
2691 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002692 }
2693 }
2694
2695 /* Collect the kernel's symbols. */
2696
2697 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002698retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002699 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002700 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002701 syms = xrealloc(syms, bufsize = ret);
2702 goto retry_kern_sym_load;
2703 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002704 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002705 return 0;
2706 }
2707 nksyms = nsyms = ret;
2708 ksyms = syms;
2709
2710 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2711 s->name += (unsigned long) syms;
2712 }
2713 return 1;
2714}
2715
2716
2717/* Return the kernel symbol checksum version, or zero if not used. */
2718
2719static int new_is_kernel_checksummed(void)
2720{
2721 struct new_module_symbol *s;
2722 size_t i;
2723
2724 /* Using_Versions is not the first symbol, but it should be in there. */
2725
2726 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2727 if (strcmp((char *) s->name, "Using_Versions") == 0)
2728 return s->value;
2729
2730 return 0;
2731}
2732
2733
2734static int new_create_this_module(struct obj_file *f, const char *m_name)
2735{
2736 struct obj_section *sec;
2737
2738 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002739 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002740 memset(sec->contents, 0, sizeof(struct new_module));
2741
Miles Baderae28b042002-04-01 09:34:25 +00002742 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002743 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002744 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002745
2746 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002747 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002748
2749 return 1;
2750}
2751
Eric Andersen889dd202003-01-23 04:48:34 +00002752#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2753/* add an entry to the __ksymtab section, creating it if necessary */
2754static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2755{
2756 struct obj_section *sec;
2757 ElfW(Addr) ofs;
2758
2759 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2760 * If __ksymtab is defined but not marked alloc, x out the first character
2761 * (no obj_delete routine) and create a new __ksymtab with the correct
2762 * characteristics.
2763 */
2764 sec = obj_find_section(f, "__ksymtab");
2765 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2766 *((char *)(sec->name)) = 'x'; /* override const */
2767 sec = NULL;
2768 }
2769 if (!sec)
2770 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002771 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002772 if (!sec)
2773 return;
2774 sec->header.sh_flags |= SHF_ALLOC;
2775 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002776 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002777 ofs = sec->header.sh_size;
2778 obj_symbol_patch(f, sec->idx, ofs, sym);
2779 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2780 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2781}
2782#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002783
2784static int new_create_module_ksymtab(struct obj_file *f)
2785{
2786 struct obj_section *sec;
2787 int i;
2788
2789 /* We must always add the module references. */
2790
2791 if (n_ext_modules_used) {
2792 struct new_module_ref *dep;
2793 struct obj_symbol *tm;
2794
2795 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002796 (sizeof(struct new_module_ref)
2797 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002798 if (!sec)
2799 return 0;
2800
Miles Baderae28b042002-04-01 09:34:25 +00002801 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002802 dep = (struct new_module_ref *) sec->contents;
2803 for (i = 0; i < n_ext_modules; ++i)
2804 if (ext_modules[i].used) {
2805 dep->dep = ext_modules[i].addr;
2806 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002807 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002808 dep->next_ref = 0;
2809 ++dep;
2810 }
2811 }
2812
2813 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2814 size_t nsyms;
2815 int *loaded;
2816
2817 sec =
2818 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002819 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002820
2821 /* We don't want to export symbols residing in sections that
2822 aren't loaded. There are a number of these created so that
2823 we make sure certain module options don't appear twice. */
2824
2825 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2826 while (--i >= 0)
2827 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2828
2829 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2830 struct obj_symbol *sym;
2831 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002832 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002833 && sym->secidx <= SHN_HIRESERVE
2834 && (sym->secidx >= SHN_LORESERVE
2835 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002836 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2837
2838 obj_symbol_patch(f, sec->idx, ofs, sym);
2839 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002840 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002841
2842 nsyms++;
2843 }
2844 }
2845
2846 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2847 }
2848
2849 return 1;
2850}
2851
2852
2853static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002854new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002855{
2856 struct new_module *module;
2857 struct obj_section *sec;
2858 void *image;
2859 int ret;
2860 tgt_long m_addr;
2861
2862 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002863 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002864 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002865 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002866 module = (struct new_module *) sec->contents;
2867 m_addr = sec->header.sh_addr;
2868
2869 module->size_of_struct = sizeof(*module);
2870 module->size = m_size;
2871 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2872
2873 sec = obj_find_section(f, "__ksymtab");
2874 if (sec && sec->header.sh_size) {
2875 module->syms = sec->header.sh_addr;
2876 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2877 }
2878
2879 if (n_ext_modules_used) {
2880 sec = obj_find_section(f, ".kmodtab");
2881 module->deps = sec->header.sh_addr;
2882 module->ndeps = n_ext_modules_used;
2883 }
2884
2885 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002886 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002887 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002888 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002889
2890 sec = obj_find_section(f, "__ex_table");
2891 if (sec) {
2892 module->ex_table_start = sec->header.sh_addr;
2893 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2894 }
2895
2896 sec = obj_find_section(f, ".text.init");
2897 if (sec) {
2898 module->runsize = sec->header.sh_addr - m_addr;
2899 }
2900 sec = obj_find_section(f, ".data.init");
2901 if (sec) {
2902 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002903 module->runsize > sec->header.sh_addr - m_addr)
2904 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002905 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002906 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2907 if (sec && sec->header.sh_size) {
2908 module->archdata_start = (void*)sec->header.sh_addr;
2909 module->archdata_end = module->archdata_start + sec->header.sh_size;
2910 }
2911 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2912 if (sec && sec->header.sh_size) {
2913 module->kallsyms_start = (void*)sec->header.sh_addr;
2914 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2915 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002916
Eric Andersen9f16d612000-06-12 23:11:16 +00002917 /* Whew! All of the initialization is complete. Collect the final
2918 module image and give it to the kernel. */
2919
2920 image = xmalloc(m_size);
2921 obj_create_image(f, image);
2922
Eric Andersencb3b9b12004-06-22 11:50:52 +00002923 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002924 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002925 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002926
2927 free(image);
2928
2929 return ret == 0;
2930}
2931
Eric Andersen9f16d612000-06-12 23:11:16 +00002932
2933/*======================================================================*/
2934
Eric Andersen044228d2001-07-17 01:12:36 +00002935static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002936obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2937 const char *string)
2938{
2939 struct obj_string_patch *p;
2940 struct obj_section *strsec;
2941 size_t len = strlen(string) + 1;
2942 char *loc;
2943
2944 p = xmalloc(sizeof(*p));
2945 p->next = f->string_patches;
2946 p->reloc_secidx = secidx;
2947 p->reloc_offset = offset;
2948 f->string_patches = p;
2949
2950 strsec = obj_find_section(f, ".kstrtab");
2951 if (strsec == NULL) {
2952 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2953 p->string_offset = 0;
2954 loc = strsec->contents;
2955 } else {
2956 p->string_offset = strsec->header.sh_size;
2957 loc = obj_extend_section(strsec, len);
2958 }
2959 memcpy(loc, string, len);
2960
2961 return 1;
2962}
2963
Eric Andersen044228d2001-07-17 01:12:36 +00002964static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002965obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2966 struct obj_symbol *sym)
2967{
2968 struct obj_symbol_patch *p;
2969
2970 p = xmalloc(sizeof(*p));
2971 p->next = f->symbol_patches;
2972 p->reloc_secidx = secidx;
2973 p->reloc_offset = offset;
2974 p->sym = sym;
2975 f->symbol_patches = p;
2976
2977 return 1;
2978}
2979
Eric Andersen044228d2001-07-17 01:12:36 +00002980static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002981{
2982 unsigned long i;
2983 int ret = 1;
2984
2985 for (i = 0; i < HASH_BUCKETS; ++i) {
2986 struct obj_symbol *sym;
2987 for (sym = f->symtab[i]; sym; sym = sym->next)
2988 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002989 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002990 sym->secidx = SHN_ABS;
2991 sym->value = 0;
2992 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002993 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002994 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00002995 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002996 ret = 0;
2997 }
2998 }
2999 }
3000
3001 return ret;
3002}
3003
Eric Andersen044228d2001-07-17 01:12:36 +00003004static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003005{
3006 struct common_entry {
3007 struct common_entry *next;
3008 struct obj_symbol *sym;
3009 } *common_head = NULL;
3010
3011 unsigned long i;
3012
3013 for (i = 0; i < HASH_BUCKETS; ++i) {
3014 struct obj_symbol *sym;
3015 for (sym = f->symtab[i]; sym; sym = sym->next)
3016 if (sym->secidx == SHN_COMMON) {
3017 /* Collect all COMMON symbols and sort them by size so as to
3018 minimize space wasted by alignment requirements. */
3019 {
3020 struct common_entry **p, *n;
3021 for (p = &common_head; *p; p = &(*p)->next)
3022 if (sym->size <= (*p)->sym->size)
3023 break;
3024
3025 n = alloca(sizeof(*n));
3026 n->next = *p;
3027 n->sym = sym;
3028 *p = n;
3029 }
3030 }
3031 }
3032
3033 for (i = 1; i < f->local_symtab_size; ++i) {
3034 struct obj_symbol *sym = f->local_symtab[i];
3035 if (sym && sym->secidx == SHN_COMMON) {
3036 struct common_entry **p, *n;
3037 for (p = &common_head; *p; p = &(*p)->next)
3038 if (sym == (*p)->sym)
3039 break;
3040 else if (sym->size < (*p)->sym->size) {
3041 n = alloca(sizeof(*n));
3042 n->next = *p;
3043 n->sym = sym;
3044 *p = n;
3045 break;
3046 }
3047 }
3048 }
3049
3050 if (common_head) {
3051 /* Find the bss section. */
3052 for (i = 0; i < f->header.e_shnum; ++i)
3053 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3054 break;
3055
3056 /* If for some reason there hadn't been one, create one. */
3057 if (i == f->header.e_shnum) {
3058 struct obj_section *sec;
3059
3060 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3061 f->sections[i] = sec = arch_new_section();
3062 f->header.e_shnum = i + 1;
3063
3064 memset(sec, 0, sizeof(*sec));
3065 sec->header.sh_type = SHT_PROGBITS;
3066 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3067 sec->name = ".bss";
3068 sec->idx = i;
3069 }
3070
3071 /* Allocate the COMMONS. */
3072 {
3073 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3074 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3075 struct common_entry *c;
3076
3077 for (c = common_head; c; c = c->next) {
3078 ElfW(Addr) align = c->sym->value;
3079
3080 if (align > max_align)
3081 max_align = align;
3082 if (bss_size & (align - 1))
3083 bss_size = (bss_size | (align - 1)) + 1;
3084
3085 c->sym->secidx = i;
3086 c->sym->value = bss_size;
3087
3088 bss_size += c->sym->size;
3089 }
3090
3091 f->sections[i]->header.sh_size = bss_size;
3092 f->sections[i]->header.sh_addralign = max_align;
3093 }
3094 }
3095
3096 /* For the sake of patch relocation and parameter initialization,
3097 allocate zeroed data for NOBITS sections now. Note that after
3098 this we cannot assume NOBITS are really empty. */
3099 for (i = 0; i < f->header.e_shnum; ++i) {
3100 struct obj_section *s = f->sections[i];
3101 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003102 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003103 s->contents = memset(xmalloc(s->header.sh_size),
3104 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003105 else
3106 s->contents = NULL;
3107
Eric Andersen9f16d612000-06-12 23:11:16 +00003108 s->header.sh_type = SHT_PROGBITS;
3109 }
3110 }
3111}
3112
Eric Andersen044228d2001-07-17 01:12:36 +00003113static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003114{
3115 unsigned long dot = 0;
3116 struct obj_section *sec;
3117
3118 /* Finalize the positions of the sections relative to one another. */
3119
3120 for (sec = f->load_order; sec; sec = sec->load_next) {
3121 ElfW(Addr) align;
3122
3123 align = sec->header.sh_addralign;
3124 if (align && (dot & (align - 1)))
3125 dot = (dot | (align - 1)) + 1;
3126
3127 sec->header.sh_addr = dot;
3128 dot += sec->header.sh_size;
3129 }
3130
3131 return dot;
3132}
3133
Eric Andersen044228d2001-07-17 01:12:36 +00003134static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003135{
3136 int i, n = f->header.e_shnum;
3137 int ret = 1;
3138
3139 /* Finalize the addresses of the sections. */
3140
3141 f->baseaddr = base;
3142 for (i = 0; i < n; ++i)
3143 f->sections[i]->header.sh_addr += base;
3144
3145 /* And iterate over all of the relocations. */
3146
3147 for (i = 0; i < n; ++i) {
3148 struct obj_section *relsec, *symsec, *targsec, *strsec;
3149 ElfW(RelM) * rel, *relend;
3150 ElfW(Sym) * symtab;
3151 const char *strtab;
3152
3153 relsec = f->sections[i];
3154 if (relsec->header.sh_type != SHT_RELM)
3155 continue;
3156
3157 symsec = f->sections[relsec->header.sh_link];
3158 targsec = f->sections[relsec->header.sh_info];
3159 strsec = f->sections[symsec->header.sh_link];
3160
3161 rel = (ElfW(RelM) *) relsec->contents;
3162 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3163 symtab = (ElfW(Sym) *) symsec->contents;
3164 strtab = (const char *) strsec->contents;
3165
3166 for (; rel < relend; ++rel) {
3167 ElfW(Addr) value = 0;
3168 struct obj_symbol *intsym = NULL;
3169 unsigned long symndx;
3170 ElfW(Sym) * extsym = 0;
3171 const char *errmsg;
3172
3173 /* Attempt to find a value to use for this relocation. */
3174
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003175 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003176 if (symndx) {
3177 /* Note we've already checked for undefined symbols. */
3178
3179 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003180 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003181 /* Local symbols we look up in the local table to be sure
3182 we get the one that is really intended. */
3183 intsym = f->local_symtab[symndx];
3184 } else {
3185 /* Others we look up in the hash table. */
3186 const char *name;
3187 if (extsym->st_name)
3188 name = strtab + extsym->st_name;
3189 else
3190 name = f->sections[extsym->st_shndx]->name;
3191 intsym = obj_find_symbol(f, name);
3192 }
3193
3194 value = obj_symbol_final_value(f, intsym);
3195 intsym->referenced = 1;
3196 }
3197#if SHT_RELM == SHT_RELA
3198#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3199 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3200 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003201 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003202#endif
3203 value += rel->r_addend;
3204#endif
3205
3206 /* Do it! */
3207 switch (arch_apply_relocation
3208 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003209 case obj_reloc_ok:
3210 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003211
Eric Andersen3b1a7442003-12-24 20:30:45 +00003212 case obj_reloc_overflow:
3213 errmsg = "Relocation overflow";
3214 goto bad_reloc;
3215 case obj_reloc_dangerous:
3216 errmsg = "Dangerous relocation";
3217 goto bad_reloc;
3218 case obj_reloc_unhandled:
3219 errmsg = "Unhandled relocation";
3220bad_reloc:
3221 if (extsym) {
3222 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003223 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003224 strtab + extsym->st_name);
3225 } else {
3226 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003227 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003228 }
3229 ret = 0;
3230 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003231 }
3232 }
3233 }
3234
3235 /* Finally, take care of the patches. */
3236
3237 if (f->string_patches) {
3238 struct obj_string_patch *p;
3239 struct obj_section *strsec;
3240 ElfW(Addr) strsec_base;
3241 strsec = obj_find_section(f, ".kstrtab");
3242 strsec_base = strsec->header.sh_addr;
3243
3244 for (p = f->string_patches; p; p = p->next) {
3245 struct obj_section *targsec = f->sections[p->reloc_secidx];
3246 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3247 = strsec_base + p->string_offset;
3248 }
3249 }
3250
3251 if (f->symbol_patches) {
3252 struct obj_symbol_patch *p;
3253
3254 for (p = f->symbol_patches; p; p = p->next) {
3255 struct obj_section *targsec = f->sections[p->reloc_secidx];
3256 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3257 = obj_symbol_final_value(f, p->sym);
3258 }
3259 }
3260
3261 return ret;
3262}
3263
Eric Andersen044228d2001-07-17 01:12:36 +00003264static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003265{
3266 struct obj_section *sec;
3267 ElfW(Addr) base = f->baseaddr;
3268
3269 for (sec = f->load_order; sec; sec = sec->load_next) {
3270 char *secimg;
3271
Eric Andersen2bf658d2001-02-24 20:01:53 +00003272 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003273 continue;
3274
3275 secimg = image + (sec->header.sh_addr - base);
3276
3277 /* Note that we allocated data for NOBITS sections earlier. */
3278 memcpy(secimg, sec->contents, sec->header.sh_size);
3279 }
3280
3281 return 1;
3282}
3283
3284/*======================================================================*/
3285
Eric Andersen044228d2001-07-17 01:12:36 +00003286static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003287{
3288 struct obj_file *f;
3289 ElfW(Shdr) * section_headers;
3290 int shnum, i;
3291 char *shstrtab;
3292
3293 /* Read the file header. */
3294
3295 f = arch_new_file();
3296 memset(f, 0, sizeof(*f));
3297 f->symbol_cmp = strcmp;
3298 f->symbol_hash = obj_elf_hash;
3299 f->load_order_search_start = &f->load_order;
3300
3301 fseek(fp, 0, SEEK_SET);
3302 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003303 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003304 return NULL;
3305 }
3306
3307 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003308 || f->header.e_ident[EI_MAG1] != ELFMAG1
3309 || f->header.e_ident[EI_MAG2] != ELFMAG2
3310 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003311 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003312 return NULL;
3313 }
3314 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003315 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
3316 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003317 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3318 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003319 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003320 return NULL;
3321 }
3322 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003323 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003324 return NULL;
3325 }
3326
3327 /* Read the section headers. */
3328
3329 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003330 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003331 (unsigned long) f->header.e_shentsize,
3332 (unsigned long) sizeof(ElfW(Shdr)));
3333 return NULL;
3334 }
3335
3336 shnum = f->header.e_shnum;
3337 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3338 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3339
3340 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3341 fseek(fp, f->header.e_shoff, SEEK_SET);
3342 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003343 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003344 return NULL;
3345 }
3346
3347 /* Read the section data. */
3348
3349 for (i = 0; i < shnum; ++i) {
3350 struct obj_section *sec;
3351
3352 f->sections[i] = sec = arch_new_section();
3353 memset(sec, 0, sizeof(*sec));
3354
3355 sec->header = section_headers[i];
3356 sec->idx = i;
3357
Eric Andersen2bf658d2001-02-24 20:01:53 +00003358 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003359 case SHT_NULL:
3360 case SHT_NOTE:
3361 case SHT_NOBITS:
3362 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003363 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003364
3365 case SHT_PROGBITS:
3366#if LOADBITS
3367 if (!loadprogbits) {
3368 sec->contents = NULL;
3369 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003370 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003371#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003372 case SHT_SYMTAB:
3373 case SHT_STRTAB:
3374 case SHT_RELM:
3375 if (sec->header.sh_size > 0) {
3376 sec->contents = xmalloc(sec->header.sh_size);
3377 fseek(fp, sec->header.sh_offset, SEEK_SET);
3378 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3379 bb_perror_msg("error reading ELF section data");
3380 return NULL;
3381 }
3382 } else {
3383 sec->contents = NULL;
3384 }
3385 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003386
3387#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003388 case SHT_RELA:
3389 bb_error_msg("RELA relocations not supported on this architecture");
3390 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003391#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003392 case SHT_REL:
3393 bb_error_msg("REL relocations not supported on this architecture");
3394 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003395#endif
3396
Eric Andersen3b1a7442003-12-24 20:30:45 +00003397 default:
3398 if (sec->header.sh_type >= SHT_LOPROC) {
3399 /* Assume processor specific section types are debug
3400 info and can safely be ignored. If this is ever not
3401 the case (Hello MIPS?), don't put ifdefs here but
3402 create an arch_load_proc_section(). */
3403 break;
3404 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003405
Eric Andersen3b1a7442003-12-24 20:30:45 +00003406 bb_error_msg("can't handle sections of type %ld",
3407 (long) sec->header.sh_type);
3408 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003409 }
3410 }
3411
3412 /* Do what sort of interpretation as needed by each section. */
3413
3414 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3415
3416 for (i = 0; i < shnum; ++i) {
3417 struct obj_section *sec = f->sections[i];
3418 sec->name = shstrtab + sec->header.sh_name;
3419 }
3420
3421 for (i = 0; i < shnum; ++i) {
3422 struct obj_section *sec = f->sections[i];
3423
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003424 /* .modinfo should be contents only but gcc has no attribute for that.
3425 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3426 */
3427 if (strcmp(sec->name, ".modinfo") == 0)
3428 sec->header.sh_flags &= ~SHF_ALLOC;
3429
Eric Andersen9f16d612000-06-12 23:11:16 +00003430 if (sec->header.sh_flags & SHF_ALLOC)
3431 obj_insert_section_load_order(f, sec);
3432
3433 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003434 case SHT_SYMTAB:
3435 {
3436 unsigned long nsym, j;
3437 char *strtab;
3438 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003439
Eric Andersen3b1a7442003-12-24 20:30:45 +00003440 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3441 bb_error_msg("symbol size mismatch: %lu != %lu",
3442 (unsigned long) sec->header.sh_entsize,
3443 (unsigned long) sizeof(ElfW(Sym)));
3444 return NULL;
3445 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003446
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3448 strtab = f->sections[sec->header.sh_link]->contents;
3449 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003450
Eric Andersen3b1a7442003-12-24 20:30:45 +00003451 /* Allocate space for a table of local symbols. */
3452 j = f->local_symtab_size = sec->header.sh_info;
3453 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003454
Eric Andersen3b1a7442003-12-24 20:30:45 +00003455 /* Insert all symbols into the hash table. */
3456 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3457 ElfW(Addr) val = sym->st_value;
3458 const char *name;
3459 if (sym->st_name)
3460 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003461 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003462 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003463 else
3464 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003465
Eric Andersenbf833552003-08-13 19:56:33 +00003466#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003467 /*
3468 * For sh64 it is possible that the target of a branch
3469 * requires a mode switch (32 to 16 and back again).
3470 *
3471 * This is implied by the lsb being set in the target
3472 * address for SHmedia mode and clear for SHcompact.
3473 */
3474 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003475#endif
3476
Eric Andersen3b1a7442003-12-24 20:30:45 +00003477 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3478 val, sym->st_size);
3479 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003480 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003481 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003482
Eric Andersen3b1a7442003-12-24 20:30:45 +00003483 case SHT_RELM:
3484 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3485 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3486 (unsigned long) sec->header.sh_entsize,
3487 (unsigned long) sizeof(ElfW(RelM)));
3488 return NULL;
3489 }
3490 break;
3491 /* XXX Relocation code from modutils-2.3.19 is not here.
3492 * Why? That's about 20 lines of code from obj/obj_load.c,
3493 * which gets done in a second pass through the sections.
3494 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003495 }
3496 }
3497
3498 return f;
3499}
3500
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003501#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003502/*
3503 * load the unloaded sections directly into the memory allocated by
3504 * kernel for the module
3505 */
3506
Eric Andersenac5dbd12001-08-22 05:26:08 +00003507static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003508{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003509 ElfW(Addr) base = f->baseaddr;
3510 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003511
Eric Andersen8ae319a2001-05-21 16:09:18 +00003512 for (sec = f->load_order; sec; sec = sec->load_next) {
3513
3514 /* section already loaded? */
3515 if (sec->contents != NULL)
3516 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003517
Eric Andersen8ae319a2001-05-21 16:09:18 +00003518 if (sec->header.sh_size == 0)
3519 continue;
3520
3521 sec->contents = imagebase + (sec->header.sh_addr - base);
3522 fseek(fp, sec->header.sh_offset, SEEK_SET);
3523 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003524 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003525 return 0;
3526 }
3527
3528 }
3529 return 1;
3530}
3531#endif
3532
Eric Andersen9f16d612000-06-12 23:11:16 +00003533static void hide_special_symbols(struct obj_file *f)
3534{
3535 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003536 SPFX "cleanup_module",
3537 SPFX "init_module",
3538 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003539 NULL
3540 };
3541
3542 struct obj_symbol *sym;
3543 const char *const *p;
3544
3545 for (p = specials; *p; ++p)
3546 if ((sym = obj_find_symbol(f, *p)) != NULL)
3547 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003548 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003549}
3550
Glenn L McGrath759515c2003-08-30 06:00:33 +00003551
Eric Andersen71ae64b2002-10-10 04:20:21 +00003552#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003553static int obj_gpl_license(struct obj_file *f, const char **license)
3554{
3555 struct obj_section *sec;
3556 /* This list must match *exactly* the list of allowable licenses in
3557 * linux/include/linux/module.h. Checking for leading "GPL" will not
3558 * work, somebody will use "GPL sucks, this is proprietary".
3559 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003560 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003561 "GPL",
3562 "GPL v2",
3563 "GPL and additional rights",
3564 "Dual BSD/GPL",
3565 "Dual MPL/GPL",
3566 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003567
Eric Andersen166fa462002-09-16 05:30:24 +00003568 if ((sec = obj_find_section(f, ".modinfo"))) {
3569 const char *value, *ptr, *endptr;
3570 ptr = sec->contents;
3571 endptr = ptr + sec->header.sh_size;
3572 while (ptr < endptr) {
3573 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3574 int i;
3575 if (license)
3576 *license = value+1;
3577 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3578 if (strcmp(value+1, gpl_licenses[i]) == 0)
3579 return(0);
3580 }
3581 return(2);
3582 }
3583 if (strchr(ptr, '\0'))
3584 ptr = strchr(ptr, '\0') + 1;
3585 else
3586 ptr = endptr;
3587 }
3588 }
3589 return(1);
3590}
3591
3592#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3593#define TAINT_PROPRIETORY_MODULE (1<<0)
3594#define TAINT_FORCED_MODULE (1<<1)
3595#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003596#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003597
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003598static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003599 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3600{
3601 char buf[80];
3602 int oldval;
3603 static int first = 1;
3604 if (fd < 0 && !kernel_has_tainted)
3605 return; /* New modutils on old kernel */
3606 printf("Warning: loading %s will taint the kernel: %s%s\n",
3607 m_name, text1, text2);
3608 if (first) {
3609 printf(" See %s for information about tainted modules\n", TAINT_URL);
3610 first = 0;
3611 }
3612 if (fd >= 0) {
3613 read(fd, buf, sizeof(buf)-1);
3614 buf[sizeof(buf)-1] = '\0';
3615 oldval = strtoul(buf, NULL, 10);
3616 sprintf(buf, "%d\n", oldval | taint);
3617 write(fd, buf, strlen(buf));
3618 }
3619}
3620
3621/* Check if loading this module will taint the kernel. */
3622static void check_tainted_module(struct obj_file *f, char *m_name)
3623{
3624 static const char tainted_file[] = TAINT_FILENAME;
3625 int fd, kernel_has_tainted;
3626 const char *ptr;
3627
3628 kernel_has_tainted = 1;
3629 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3630 if (errno == ENOENT)
3631 kernel_has_tainted = 0;
3632 else if (errno == EACCES)
3633 kernel_has_tainted = 1;
3634 else {
3635 perror(tainted_file);
3636 kernel_has_tainted = 0;
3637 }
3638 }
3639
3640 switch (obj_gpl_license(f, &ptr)) {
3641 case 0:
3642 break;
3643 case 1:
3644 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3645 break;
3646 case 2:
3647 /* The module has a non-GPL license so we pretend that the
3648 * kernel always has a taint flag to get a warning even on
3649 * kernels without the proc flag.
3650 */
3651 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3652 break;
3653 default:
3654 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3655 break;
3656 }
3657
3658 if (flag_force_load)
3659 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3660
3661 if (fd >= 0)
3662 close(fd);
3663}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003664#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3665#define check_tainted_module(x, y) do { } while(0);
3666#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003667
Eric Andersen889dd202003-01-23 04:48:34 +00003668#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3669/* add module source, timestamp, kernel version and a symbol for the
3670 * start of some sections. this info is used by ksymoops to do better
3671 * debugging.
3672 */
3673static int
3674get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3675{
3676#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003677 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003678#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003679 strncpy(str, "???", sizeof(str));
3680 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003681#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3682}
3683
3684/* add module source, timestamp, kernel version and a symbol for the
3685 * start of some sections. this info is used by ksymoops to do better
3686 * debugging.
3687 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003688static void
Eric Andersen889dd202003-01-23 04:48:34 +00003689add_ksymoops_symbols(struct obj_file *f, const char *filename,
3690 const char *m_name)
3691{
3692 static const char symprefix[] = "__insmod_";
3693 struct obj_section *sec;
3694 struct obj_symbol *sym;
3695 char *name, *absolute_filename;
3696 char str[STRVERSIONLEN], real[PATH_MAX];
3697 int i, l, lm_name, lfilename, use_ksymtab, version;
3698 struct stat statbuf;
3699
3700 static const char *section_names[] = {
3701 ".text",
3702 ".rodata",
3703 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003704 ".bss",
3705 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003706 };
3707
3708 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003709 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003710 }
3711 else {
3712 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003713 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003714 errno = save_errno;
3715 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003716 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003717 }
3718
3719 lm_name = strlen(m_name);
3720 lfilename = strlen(absolute_filename);
3721
3722 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3723 * are not to be exported. otherwise leave ksymtab alone for now, the
3724 * "export all symbols" compatibility code will export these symbols later.
3725 */
3726 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3727
3728 if ((sec = obj_find_section(f, ".this"))) {
3729 /* tag the module header with the object name, last modified
3730 * timestamp and module version. worst case for module version
3731 * is 0xffffff, decimal 16777215. putting all three fields in
3732 * one symbol is less readable but saves kernel space.
3733 */
3734 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003735 lm_name+ /* module name */
3736 2+ /* "_O" */
3737 lfilename+ /* object filename */
3738 2+ /* "_M" */
3739 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3740 2+ /* "_V" */
3741 8+ /* version in dec */
3742 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003743 name = xmalloc(l);
3744 if (stat(absolute_filename, &statbuf) != 0)
3745 statbuf.st_mtime = 0;
3746 version = get_module_version(f, str); /* -1 if not found */
3747 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003748 symprefix, m_name, absolute_filename,
3749 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3750 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003751 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003752 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003753 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003754 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003755 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003756 }
3757 free(absolute_filename);
3758#ifdef _NOT_SUPPORTED_
3759 /* record where the persistent data is going, same address as previous symbol */
3760
3761 if (f->persist) {
3762 l = sizeof(symprefix)+ /* "__insmod_" */
3763 lm_name+ /* module name */
3764 2+ /* "_P" */
3765 strlen(f->persist)+ /* data store */
3766 1; /* nul */
3767 name = xmalloc(l);
3768 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003769 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003770 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003771 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003772 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003773 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003774 }
3775#endif /* _NOT_SUPPORTED_ */
3776 /* tag the desired sections if size is non-zero */
3777
3778 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3779 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003780 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003781 l = sizeof(symprefix)+ /* "__insmod_" */
3782 lm_name+ /* module name */
3783 2+ /* "_S" */
3784 strlen(sec->name)+ /* section name */
3785 2+ /* "_L" */
3786 8+ /* length in dec */
3787 1; /* nul */
3788 name = xmalloc(l);
3789 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003790 symprefix, m_name, sec->name,
3791 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003792 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003793 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003794 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003795 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003796 }
3797 }
3798}
3799#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3800
Eric Andersenbe65c352003-01-23 04:57:35 +00003801#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3802static void print_load_map(struct obj_file *f)
3803{
3804 struct obj_symbol *sym;
3805 struct obj_symbol **all, **p;
3806 struct obj_section *sec;
3807 int i, nsyms, *loaded;
3808
3809 /* Report on the section layout. */
3810
3811 printf("Sections: Size %-*s Align\n",
3812 (int) (2 * sizeof(void *)), "Address");
3813
3814 for (sec = f->load_order; sec; sec = sec->load_next) {
3815 int a;
3816 unsigned long tmp;
3817
3818 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3819 tmp >>= 1;
3820 if (a == -1)
3821 a = 0;
3822
3823 printf("%-15s %08lx %0*lx 2**%d\n",
3824 sec->name,
3825 (long)sec->header.sh_size,
3826 (int) (2 * sizeof(void *)),
3827 (long)sec->header.sh_addr,
3828 a);
3829 }
3830#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3831 /* Quick reference which section indicies are loaded. */
3832
3833 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3834 while (--i >= 0)
3835 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3836
3837 /* Collect the symbols we'll be listing. */
3838
3839 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3840 for (sym = f->symtab[i]; sym; sym = sym->next)
3841 if (sym->secidx <= SHN_HIRESERVE
3842 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3843 ++nsyms;
3844
3845 all = alloca(nsyms * sizeof(struct obj_symbol *));
3846
3847 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3848 for (sym = f->symtab[i]; sym; sym = sym->next)
3849 if (sym->secidx <= SHN_HIRESERVE
3850 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3851 *p++ = sym;
3852
3853 /* And list them. */
3854 printf("\nSymbols:\n");
3855 for (p = all; p < all + nsyms; ++p) {
3856 char type = '?';
3857 unsigned long value;
3858
3859 sym = *p;
3860 if (sym->secidx == SHN_ABS) {
3861 type = 'A';
3862 value = sym->value;
3863 } else if (sym->secidx == SHN_UNDEF) {
3864 type = 'U';
3865 value = 0;
3866 } else {
3867 sec = f->sections[sym->secidx];
3868
3869 if (sec->header.sh_type == SHT_NOBITS)
3870 type = 'B';
3871 else if (sec->header.sh_flags & SHF_ALLOC) {
3872 if (sec->header.sh_flags & SHF_EXECINSTR)
3873 type = 'T';
3874 else if (sec->header.sh_flags & SHF_WRITE)
3875 type = 'D';
3876 else
3877 type = 'R';
3878 }
3879 value = sym->value + sec->header.sh_addr;
3880 }
3881
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003882 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003883 type = tolower(type);
3884
3885 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3886 type, sym->name);
3887 }
3888#endif
3889}
3890
3891#endif
3892
Rob Landleydfba7412006-03-06 20:47:33 +00003893int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003894{
Eric Andersena18aaf12001-01-24 19:07:09 +00003895 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003896 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003897 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003898 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003899 unsigned long m_size;
3900 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003901 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003902 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003903 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003904 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003905 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003906#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003907 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003908 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003909 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003910#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003911#ifdef CONFIG_FEATURE_CLEAN_UP
3912 FILE *fp = 0;
3913#else
3914 FILE *fp;
3915#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003916#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3917 int flag_print_load_map = 0;
3918#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003919 int k_version = 0;
3920 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003921
Erik Andersene49d5ec2000-02-08 19:58:47 +00003922 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003923#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003924 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003925#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003926 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003927#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003928 {
3929 switch (opt) {
3930 case 'f': /* force loading */
3931 flag_force_load = 1;
3932 break;
3933 case 'k': /* module loaded by kerneld, auto-cleanable */
3934 flag_autoclean = 1;
3935 break;
3936 case 's': /* log to syslog */
3937 /* log to syslog -- not supported */
3938 /* but kernel needs this for request_module(), */
3939 /* as this calls: modprobe -k -s -- <module> */
3940 /* so silently ignore this flag */
3941 break;
3942 case 'v': /* verbose output */
3943 flag_verbose = 1;
3944 break;
3945 case 'q': /* silent */
3946 flag_quiet = 1;
3947 break;
3948 case 'x': /* do not export externs */
3949 flag_export = 0;
3950 break;
3951 case 'o': /* name the output module */
3952 free(m_name);
3953 m_name = bb_xstrdup(optarg);
3954 break;
3955 case 'L': /* Stub warning */
3956 /* This is needed for compatibility with modprobe.
3957 * In theory, this does locking, but we don't do
3958 * that. So be careful and plan your life around not
3959 * loading the same module 50 times concurrently. */
3960 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003961#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003962 case 'm': /* print module load map */
3963 flag_print_load_map = 1;
3964 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003965#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003966 default:
3967 bb_show_usage();
3968 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003969 }
Eric Andersen03d80912003-12-19 21:04:19 +00003970
Eric Andersena18aaf12001-01-24 19:07:09 +00003971 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003972 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003973 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003974
Erik Andersene49d5ec2000-02-08 19:58:47 +00003975 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003976 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003977 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003978 len = strlen(tmp);
3979
Eric Andersen03d80912003-12-19 21:04:19 +00003980 if (uname(&myuname) == 0) {
3981 if (myuname.release[0] == '2') {
3982 k_version = myuname.release[2] - '0';
3983 }
3984 }
3985
3986#if defined(CONFIG_FEATURE_2_6_MODULES)
3987 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003988 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003989 len-=3;
3990 tmp[len] = '\0';
3991 }
3992 else
3993#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003994 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3995 len-=2;
3996 tmp[len] = '\0';
3997 }
Eric Andersen2d342152002-06-18 05:16:25 +00003998
Eric Andersen03d80912003-12-19 21:04:19 +00003999
4000#if defined(CONFIG_FEATURE_2_6_MODULES)
4001 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004002 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004003 else
Eric Andersen03d80912003-12-19 21:04:19 +00004004#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004005 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004006
Eric Andersen61f83052002-06-22 17:15:42 +00004007 if (!m_name) {
4008 m_name = tmp;
4009 } else {
4010 free(tmp1);
4011 tmp1 = 0; /* flag for free(m_name) before exit() */
4012 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004013
Eric Andersen14d35432001-05-14 17:07:32 +00004014 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004015 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4016 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004017 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4018 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004019 if (k_version) { /* uname succeedd */
4020 char *module_dir;
4021 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004022 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004023
Eric Andersen03d80912003-12-19 21:04:19 +00004024 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004025 /* Jump through hoops in case /lib/modules/`uname -r`
4026 * is a symlink. We do not want recursive_action to
4027 * follow symlinks, but we do want to follow the
4028 * /lib/modules/`uname -r` dir, So resolve it ourselves
4029 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004030 if (realpath (tmdn, real_module_dir) == NULL)
4031 module_dir = tmdn;
4032 else
4033 module_dir = real_module_dir;
4034 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004035 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004036 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004037 }
4038
4039 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004040 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004041 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004042 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004043
Eric Andersen03d80912003-12-19 21:04:19 +00004044 free(m_filename);
4045 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004046 if (realpath (_PATH_MODULES, module_dir) == NULL)
4047 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004048 /* No module found under /lib/modules/`uname -r`, this
4049 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004050 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004051 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004052 {
Eric Andersen61f83052002-06-22 17:15:42 +00004053 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004054 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004055 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004056 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004057 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004058 }
4059 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004060 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004061 }
Eric Andersen03d80912003-12-19 21:04:19 +00004062 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004063 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004064
Rob Landley999af202005-12-11 20:14:12 +00004065 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004066 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004067
Eric Andersene7047882003-12-11 01:42:13 +00004068#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004069 if (k_version > 4)
4070 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004071 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004072 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004073 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004074 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004075#endif
4076
Eric Andersen8ae319a2001-05-21 16:09:18 +00004077 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004078 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004079
Eric Andersen9f16d612000-06-12 23:11:16 +00004080 if (get_modinfo_value(f, "kernel_version") == NULL)
4081 m_has_modinfo = 0;
4082 else
4083 m_has_modinfo = 1;
4084
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004085#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004086 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004087 if (!flag_quiet) {
4088 if (uname(&uts_info) < 0)
4089 uts_info.release[0] = '\0';
4090 if (m_has_modinfo) {
4091 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004092 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004093 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004094 "compiled for");
4095 goto out;
4096 }
4097 }
4098
4099 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4100 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004101 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004102 "\t%s was compiled for kernel version %s\n"
4103 "\twhile this kernel is version %s",
4104 m_filename, m_strversion, uts_info.release);
4105 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004106 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004107 "\t%s was compiled for kernel version %s\n"
4108 "\twhile this kernel is version %s.",
4109 m_filename, m_strversion, uts_info.release);
4110 goto out;
4111 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004112 }
4113 }
4114 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004115#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004116
Eric Andersencb3b9b12004-06-22 11:50:52 +00004117 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004118 if (!new_get_kernel_symbols())
4119 goto out;
4120 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004121 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004122 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004123 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004124 }
4125
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004126#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004127 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004128 if (m_has_modinfo)
4129 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004130
4131 if (m_crcs != k_crcs)
4132 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004133#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004134
Erik Andersene49d5ec2000-02-08 19:58:47 +00004135 /* Let the module know about the kernel symbols. */
4136 add_kernel_symbols(f);
4137
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 /* Allocate common symbols, symbol tables, and string tables. */
4139
Eric Andersencb3b9b12004-06-22 11:50:52 +00004140 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004141 {
4142 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004143 }
4144
Eric Andersen9f16d612000-06-12 23:11:16 +00004145 if (!obj_check_undefineds(f)) {
4146 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004147 }
4148 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004149 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004150
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004151 /* done with the module name, on to the optional var=value arguments */
4152 ++optind;
4153
Eric Andersen9f16d612000-06-12 23:11:16 +00004154 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004155 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 {
4157 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004158 }
4159 }
4160
Eric Andersen9f16d612000-06-12 23:11:16 +00004161 arch_create_got(f);
4162 hide_special_symbols(f);
4163
Eric Andersen889dd202003-01-23 04:48:34 +00004164#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4165 add_ksymoops_symbols(f, m_filename, m_name);
4166#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4167
Eric Andersencb3b9b12004-06-22 11:50:52 +00004168 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004169
Erik Andersene49d5ec2000-02-08 19:58:47 +00004170 /* Find current size of the module */
4171 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004172
4173
Erik Andersene49d5ec2000-02-08 19:58:47 +00004174 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004175 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004176 case EEXIST:
4177 bb_error_msg("A module named %s already exists", m_name);
4178 goto out;
4179 case ENOMEM:
4180 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4181 m_size);
4182 goto out;
4183 default:
4184 bb_perror_msg("create_module: %s", m_name);
4185 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004186 }
Erik Andersend387d011999-12-21 02:55:11 +00004187
Eric Andersen8ae319a2001-05-21 16:09:18 +00004188#if !LOADBITS
4189 /*
4190 * the PROGBITS section was not loaded by the obj_load
4191 * now we can load them directly into the kernel memory
4192 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004193 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004194 delete_module(m_name);
4195 goto out;
4196 }
Eric Andersen03d80912003-12-19 21:04:19 +00004197#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004198
Eric Andersen9f16d612000-06-12 23:11:16 +00004199 if (!obj_relocate(f, m_addr)) {
4200 delete_module(m_name);
4201 goto out;
4202 }
Erik Andersend387d011999-12-21 02:55:11 +00004203
Eric Andersencb3b9b12004-06-22 11:50:52 +00004204 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004205 {
4206 delete_module(m_name);
4207 goto out;
4208 }
4209
Eric Andersenbe65c352003-01-23 04:57:35 +00004210#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4211 if(flag_print_load_map)
4212 print_load_map(f);
4213#endif
4214
Matt Kraai3e856ce2000-12-01 02:55:13 +00004215 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004216
4217out:
Eric Andersen61f83052002-06-22 17:15:42 +00004218#ifdef CONFIG_FEATURE_CLEAN_UP
4219 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004220 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004221 free(tmp1);
4222 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004223 free(m_name);
4224 }
4225 free(m_filename);
4226#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004227 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004228}
Eric Andersene7047882003-12-11 01:42:13 +00004229
4230
4231#endif
4232
4233
4234#ifdef CONFIG_FEATURE_2_6_MODULES
4235
4236#include <sys/mman.h>
4237#include <asm/unistd.h>
4238#include <sys/syscall.h>
4239
4240/* We use error numbers in a loose translation... */
4241static const char *moderror(int err)
4242{
4243 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004244 case ENOEXEC:
4245 return "Invalid module format";
4246 case ENOENT:
4247 return "Unknown symbol in module";
4248 case ESRCH:
4249 return "Module has wrong symbol version";
4250 case EINVAL:
4251 return "Invalid parameters";
4252 default:
4253 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004254 }
4255}
4256
Rob Landleydfba7412006-03-06 20:47:33 +00004257int insmod_ng_main( int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004258{
4259 int i;
4260 int fd;
4261 long int ret;
4262 struct stat st;
4263 unsigned long len;
4264 void *map;
4265 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004266
Eric Andersene7047882003-12-11 01:42:13 +00004267 filename = argv[1];
4268 if (!filename) {
4269 bb_show_usage();
4270 return -1;
4271 }
4272
4273 /* Rest is options */
4274 for (i = 2; i < argc; i++) {
4275 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4276 /* Spaces handled by "" pairs, but no way of escaping quotes */
4277 if (strchr(argv[i], ' ')) {
4278 strcat(options, "\"");
4279 strcat(options, argv[i]);
4280 strcat(options, "\"");
4281 } else {
4282 strcat(options, argv[i]);
4283 }
4284 strcat(options, " ");
4285 }
4286
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +00004287 fd = bb_xopen3(filename, O_RDONLY, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004288
4289 fstat(fd, &st);
4290 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004291 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004292 if (map == MAP_FAILED) {
4293 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4294 }
4295
4296 ret = syscall(__NR_init_module, map, len, options);
4297 if (ret != 0) {
4298 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004299 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004300 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004301
Eric Andersene7047882003-12-11 01:42:13 +00004302 return 0;
4303}
4304
4305#endif