blob: 232a6e6919924fc1a682656f1aa4de8346479b73 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
Eric Andersen2835efe2001-07-25 16:58:58 +00004 *
Eric Andersen45a05132004-09-02 23:03:25 +00005 * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
6 * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00008 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +00009 * and Ron Alder <alder@lineo.com>
10 *
Eric Andersena4d27d22004-08-19 19:17:30 +000011 * Rodney Radford <rradford@mindspring.com> 17-Aug-2004.
12 * Added x86_64 support.
13 *
Miles Bader75ce8d72002-04-01 14:25:51 +000014 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000015 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000017 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
18 *
19 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
20 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
21 * very minor changes required to also work with StrongArm and presumably
22 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000023 *
Eric Andersenee70fa52004-05-26 11:38:46 +000024 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
25 * added Renesas H8/300 support.
26 *
Eric Andersenbf833552003-08-13 19:56:33 +000027 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
28 * Integrated support for sh64 (SH-5), from preliminary modutils
29 * patches from Benedict Gaster <benedict.gaster@superh.com>.
30 * Currently limited to support for 32bit ABI.
31 *
Eric Andersencffd5022002-05-24 06:50:15 +000032 * Magnus Damm <damm@opensource.se> 22-May-2002.
33 * The plt and got code are now using the same structs.
34 * Added generic linked list code to fully support PowerPC.
35 * Replaced the mess in arch_apply_relocation() with architecture blocks.
36 * The arch_create_got() function got cleaned up with architecture blocks.
37 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
38 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000040 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
42 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000043 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000044 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000045 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
46 * based on modutils-2.4.2
47 * MIPS specific support for Elf loading and relocation.
48 * Copyright 1996, 1997 Linux International.
49 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
50 *
Eric Andersen9f16d612000-06-12 23:11:16 +000051 * Based almost entirely on the Linux modutils-2.3.11 implementation.
52 * Copyright 1996, 1997 Linux International.
53 * New implementation contributed by Richard Henderson <rth@tamu.edu>
54 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
55 * Restructured (and partly rewritten) by:
56 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000057 *
58 * This program is free software; you can redistribute it and/or modify
59 * it under the terms of the GNU General Public License as published by
60 * the Free Software Foundation; either version 2 of the License, or
61 * (at your option) any later version.
62 *
63 * This program is distributed in the hope that it will be useful,
64 * but WITHOUT ANY WARRANTY; without even the implied warranty of
65 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
66 * General Public License for more details.
67 *
68 * You should have received a copy of the GNU General Public License
69 * along with this program; if not, write to the Free Software
70 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71 *
72 */
73
Erik Andersen02104321999-12-17 18:57:34 +000074#include <stdlib.h>
75#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000076#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000077#include <errno.h>
78#include <unistd.h>
79#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000080#include <ctype.h>
81#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000082#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000083#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000084#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000085#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000086#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000087
Eric Andersene7047882003-12-11 01:42:13 +000088#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
Eric Andersene7047882003-12-11 01:42:13 +000089 !defined(CONFIG_FEATURE_2_6_MODULES)
90#define CONFIG_FEATURE_2_4_MODULES
91#endif
92
Eric Andersencb3b9b12004-06-22 11:50:52 +000093#if !defined(CONFIG_FEATURE_2_4_MODULES)
Eric Andersene7047882003-12-11 01:42:13 +000094#define insmod_ng_main insmod_main
95#endif
96
Eric Andersene7047882003-12-11 01:42:13 +000097#if defined(CONFIG_FEATURE_2_6_MODULES)
98extern int insmod_ng_main( int argc, char **argv);
99#endif
100
Eric Andersencb3b9b12004-06-22 11:50:52 +0000101
102#if defined(CONFIG_FEATURE_2_4_MODULES)
103
Eric Andersen64c8b172001-04-05 07:33:10 +0000104
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000105#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000106#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +0000107#else
108#define LOADBITS 1
109#endif
110
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000111
Mike Frysinger63654c12004-12-26 09:13:32 +0000112/* Alpha */
113#if defined(__alpha__)
114#define MATCH_MACHINE(x) (x == EM_ALPHA)
115#define SHT_RELM SHT_RELA
116#define Elf64_RelM Elf64_Rela
117#define ELFCLASSM ELFCLASS64
118#endif
119
Eric Andersen45a05132004-09-02 23:03:25 +0000120/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000121#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +0000122#define MATCH_MACHINE(x) (x == EM_ARM)
123#define SHT_RELM SHT_REL
124#define Elf32_RelM Elf32_Rel
125#define ELFCLASSM ELFCLASS32
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000126#define CONFIG_USE_PLT_ENTRIES
127#define CONFIG_PLT_ENTRY_SIZE 8
128#define CONFIG_USE_GOT_ENTRIES
129#define CONFIG_GOT_ENTRY_SIZE 8
130#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000131#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000132
Eric Andersen45a05132004-09-02 23:03:25 +0000133/* CRIS */
134#if defined(__cris__)
135#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000136#define SHT_RELM SHT_RELA
137#define Elf32_RelM Elf32_Rela
138#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000139#ifndef EM_CRIS
140#define EM_CRIS 76
141#define R_CRIS_NONE 0
142#define R_CRIS_32 3
143#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000144#endif
145
Mike Frysinger63654c12004-12-26 09:13:32 +0000146/* PA-RISC / HP-PA */
147#if defined(__hppa__)
148#define MATCH_MACHINE(x) (x == EM_PARISC)
149#define SHT_RELM SHT_RELA
150#if defined(__LP64__)
151#define Elf64_RelM Elf64_Rela
152#define ELFCLASSM ELFCLASS64
153#else
154#define Elf32_RelM Elf32_Rela
155#define ELFCLASSM ELFCLASS32
156#endif
157#endif
158
Eric Andersen45a05132004-09-02 23:03:25 +0000159/* H8/300 */
160#if defined(__H8300H__) || defined(__H8300S__)
161#define MATCH_MACHINE(x) (x == EM_H8_300)
162#define SHT_RELM SHT_RELA
163#define Elf32_RelM Elf32_Rela
164#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000165#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000166#define SYMBOL_PREFIX "_"
167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* x86 */
170#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000171#ifndef EM_486
172#define MATCH_MACHINE(x) (x == EM_386)
173#else
174#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
175#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000176#define SHT_RELM SHT_REL
177#define Elf32_RelM Elf32_Rel
178#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define CONFIG_USE_GOT_ENTRIES
180#define CONFIG_GOT_ENTRY_SIZE 4
181#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000182#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000183
Eric Andersen45a05132004-09-02 23:03:25 +0000184/* IA64, aka Itanium */
185#if defined(__ia64__)
186#define MATCH_MACHINE(x) (x == EM_IA_64)
187#define SHT_RELM SHT_RELA
188#define Elf64_RelM Elf64_Rela
189#define ELFCLASSM ELFCLASS64
190#endif
191
192/* m68k */
193#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000194#define MATCH_MACHINE(x) (x == EM_68K)
195#define SHT_RELM SHT_RELA
196#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000197#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000198#define CONFIG_USE_GOT_ENTRIES
199#define CONFIG_GOT_ENTRY_SIZE 4
200#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000201#endif
202
Eric Andersen45a05132004-09-02 23:03:25 +0000203/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000204#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000205#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
206#define SHT_RELM SHT_REL
207#define Elf32_RelM Elf32_Rel
208#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000209/* Account for ELF spec changes. */
210#ifndef EM_MIPS_RS3_LE
211#ifdef EM_MIPS_RS4_BE
212#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
213#else
214#define EM_MIPS_RS3_LE 10
215#endif
216#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000217#define ARCHDATAM "__dbe_table"
218#endif
219
Eric Andersen45a05132004-09-02 23:03:25 +0000220/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000221#if defined(__powerpc64__)
222#define MATCH_MACHINE(x) (x == EM_PPC64)
223#define SHT_RELM SHT_RELA
224#define Elf64_RelM Elf64_Rela
225#define ELFCLASSM ELFCLASS64
226#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000227#define MATCH_MACHINE(x) (x == EM_PPC)
228#define SHT_RELM SHT_RELA
229#define Elf32_RelM Elf32_Rela
230#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000231#define CONFIG_USE_PLT_ENTRIES
232#define CONFIG_PLT_ENTRY_SIZE 16
233#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000234#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000235#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000236#define ARCHDATAM "__ftr_fixup"
237#endif
238
Eric Andersen45a05132004-09-02 23:03:25 +0000239/* S390 */
240#if defined(__s390__)
241#define MATCH_MACHINE(x) (x == EM_S390)
242#define SHT_RELM SHT_RELA
243#define Elf32_RelM Elf32_Rela
244#define ELFCLASSM ELFCLASS32
245#define CONFIG_USE_PLT_ENTRIES
246#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000247#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000248#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000249#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000250#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000251
Eric Andersen45a05132004-09-02 23:03:25 +0000252/* SuperH */
253#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000254#define MATCH_MACHINE(x) (x == EM_SH)
255#define SHT_RELM SHT_RELA
256#define Elf32_RelM Elf32_Rela
257#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000258#define CONFIG_USE_GOT_ENTRIES
259#define CONFIG_GOT_ENTRY_SIZE 4
260#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000261/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000262/* I'm not sure about big endian, so let's warn: */
Eric Andersenbf833552003-08-13 19:56:33 +0000263#if defined(__sh__) && defined(__BIG_ENDIAN__)
264#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000265#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000266/* it may or may not work on the SH1/SH2... Error on those also */
267#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000268#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000269#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000270#endif
271
Eric Andersen45a05132004-09-02 23:03:25 +0000272/* Sparc */
273#if defined(__sparc__)
274#define MATCH_MACHINE(x) (x == EM_SPARC)
275#define SHT_RELM SHT_RELA
276#define Elf32_RelM Elf32_Rela
277#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000278#endif
279
Eric Andersen45a05132004-09-02 23:03:25 +0000280/* v850e */
281#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000282#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
283#define SHT_RELM SHT_RELA
284#define Elf32_RelM Elf32_Rela
285#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000286#define CONFIG_USE_PLT_ENTRIES
287#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000288#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000289#ifndef EM_CYGNUS_V850 /* grumble */
290#define EM_CYGNUS_V850 0x9080
291#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000292#define SYMBOL_PREFIX "_"
293#endif
294
Eric Andersen45a05132004-09-02 23:03:25 +0000295/* X86_64 */
296#if defined(__x86_64__)
297#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000298#define SHT_RELM SHT_RELA
299#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000300#define ELFCLASSM ELFCLASS64
301#endif
302
Eric Andersencffd5022002-05-24 06:50:15 +0000303#ifndef SHT_RELM
304#error Sorry, but insmod.c does not yet support this architecture...
305#endif
306
307
Eric Andersen9f16d612000-06-12 23:11:16 +0000308//----------------------------------------------------------------------------
309//--------modutils module.h, lines 45-242
310//----------------------------------------------------------------------------
311
312/* Definitions for the Linux module syscall interface.
313 Copyright 1996, 1997 Linux International.
314
315 Contributed by Richard Henderson <rth@tamu.edu>
316
317 This file is part of the Linux modutils.
318
319 This program is free software; you can redistribute it and/or modify it
320 under the terms of the GNU General Public License as published by the
321 Free Software Foundation; either version 2 of the License, or (at your
322 option) any later version.
323
324 This program is distributed in the hope that it will be useful, but
325 WITHOUT ANY WARRANTY; without even the implied warranty of
326 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
327 General Public License for more details.
328
329 You should have received a copy of the GNU General Public License
330 along with this program; if not, write to the Free Software Foundation,
331 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
332
333
334#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000335static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000336
Mike Frysinger63654c12004-12-26 09:13:32 +0000337#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000338
339/*======================================================================*/
340/* For sizeof() which are related to the module platform and not to the
341 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
342
343#define tgt_sizeof_char sizeof(char)
344#define tgt_sizeof_short sizeof(short)
345#define tgt_sizeof_int sizeof(int)
346#define tgt_sizeof_long sizeof(long)
347#define tgt_sizeof_char_p sizeof(char *)
348#define tgt_sizeof_void_p sizeof(void *)
349#define tgt_long long
350
351#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
352#undef tgt_sizeof_long
353#undef tgt_sizeof_char_p
354#undef tgt_sizeof_void_p
355#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000356static const int tgt_sizeof_long = 8;
357static const int tgt_sizeof_char_p = 8;
358static const int tgt_sizeof_void_p = 8;
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. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000433static const int NEW_MOD_RUNNING = 1;
434static const int NEW_MOD_DELETED = 2;
435static const int NEW_MOD_AUTOCLEAN = 4;
436static const int NEW_MOD_VISITED = 8;
437static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000438
Eric Andersencb3b9b12004-06-22 11:50:52 +0000439int init_module(const char *name, const struct new_module *);
440int query_module(const char *name, int which, void *buf,
441 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000442
443/* Values for query_module's which. */
444
Mark Whitley59ab0252001-01-23 22:30:04 +0000445static const int QM_MODULES = 1;
446static const int QM_DEPS = 2;
447static const int QM_REFS = 3;
448static const int QM_SYMBOLS = 4;
449static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000450
451/*======================================================================*/
452/* The system calls unchanged between 2.0 and 2.1. */
453
454unsigned long create_module(const char *, size_t);
455int delete_module(const char *);
456
457
458#endif /* module.h */
459
460//----------------------------------------------------------------------------
461//--------end of modutils module.h
462//----------------------------------------------------------------------------
463
464
465
466//----------------------------------------------------------------------------
467//--------modutils obj.h, lines 253-462
468//----------------------------------------------------------------------------
469
470/* Elf object file loading and relocation routines.
471 Copyright 1996, 1997 Linux International.
472
473 Contributed by Richard Henderson <rth@tamu.edu>
474
475 This file is part of the Linux modutils.
476
477 This program is free software; you can redistribute it and/or modify it
478 under the terms of the GNU General Public License as published by the
479 Free Software Foundation; either version 2 of the License, or (at your
480 option) any later version.
481
482 This program is distributed in the hope that it will be useful, but
483 WITHOUT ANY WARRANTY; without even the implied warranty of
484 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
485 General Public License for more details.
486
487 You should have received a copy of the GNU General Public License
488 along with this program; if not, write to the Free Software Foundation,
489 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
490
491
492#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000493static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000494
Mike Frysinger63654c12004-12-26 09:13:32 +0000495#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000496
497/* The relocatable object is manipulated using elfin types. */
498
499#include <stdio.h>
500#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000501#include <endian.h>
502
503#if __BYTE_ORDER == __LITTLE_ENDIAN
504#define ELFDATAM ELFDATA2LSB
505#elif __BYTE_ORDER == __BIG_ENDIAN
506#define ELFDATAM ELFDATA2MSB
507#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000508
Eric Andersen9f16d612000-06-12 23:11:16 +0000509#ifndef ElfW
510# if ELFCLASSM == ELFCLASS32
511# define ElfW(x) Elf32_ ## x
512# define ELFW(x) ELF32_ ## x
513# else
514# define ElfW(x) Elf64_ ## x
515# define ELFW(x) ELF64_ ## x
516# endif
517#endif
518
Eric Andersen85e5e722003-07-22 08:56:55 +0000519/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000520#ifndef ELF32_ST_INFO
521# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
522#endif
523
524#ifndef ELF64_ST_INFO
525# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
526#endif
527
528struct obj_string_patch;
529struct obj_symbol_patch;
530
531struct obj_section
532{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000533 ElfW(Shdr) header;
534 const char *name;
535 char *contents;
536 struct obj_section *load_next;
537 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000538};
539
540struct obj_symbol
541{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000542 struct obj_symbol *next; /* hash table link */
543 const char *name;
544 unsigned long value;
545 unsigned long size;
546 int secidx; /* the defining section index/module */
547 int info;
548 int ksymidx; /* for export to the kernel symtab */
549 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000550};
551
552/* Hardcode the hash table size. We shouldn't be needing so many
553 symbols that we begin to degrade performance, and we get a big win
554 by giving the compiler a constant divisor. */
555
556#define HASH_BUCKETS 521
557
558struct obj_file
559{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000560 ElfW(Ehdr) header;
561 ElfW(Addr) baseaddr;
562 struct obj_section **sections;
563 struct obj_section *load_order;
564 struct obj_section **load_order_search_start;
565 struct obj_string_patch *string_patches;
566 struct obj_symbol_patch *symbol_patches;
567 int (*symbol_cmp)(const char *, const char *);
568 unsigned long (*symbol_hash)(const char *);
569 unsigned long local_symtab_size;
570 struct obj_symbol **local_symtab;
571 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000572};
573
574enum obj_reloc
575{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000576 obj_reloc_ok,
577 obj_reloc_overflow,
578 obj_reloc_dangerous,
579 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000580};
581
582struct obj_string_patch
583{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000584 struct obj_string_patch *next;
585 int reloc_secidx;
586 ElfW(Addr) reloc_offset;
587 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000588};
589
590struct obj_symbol_patch
591{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000592 struct obj_symbol_patch *next;
593 int reloc_secidx;
594 ElfW(Addr) reloc_offset;
595 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000596};
597
598
599/* Generic object manipulation routines. */
600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000602
Eric Andersen044228d2001-07-17 01:12:36 +0000603static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000604
Eric Andersen044228d2001-07-17 01:12:36 +0000605static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000606 const char *name);
607
Eric Andersen044228d2001-07-17 01:12:36 +0000608static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000609 struct obj_symbol *sym);
610
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000611#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000612static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000613 int (*cmp)(const char *, const char *),
614 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000615#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000618 const char *name);
619
Eric Andersen044228d2001-07-17 01:12:36 +0000620static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000621 struct obj_section *sec);
622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000624 const char *name,
625 unsigned long align,
626 unsigned long size);
627
Eric Andersen044228d2001-07-17 01:12:36 +0000628static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000629 const char *name,
630 unsigned long align,
631 unsigned long size);
632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000634
Eric Andersen044228d2001-07-17 01:12:36 +0000635static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000636 const char *string);
637
Eric Andersen044228d2001-07-17 01:12:36 +0000638static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000639 struct obj_symbol *sym);
640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000642
Eric Andersen044228d2001-07-17 01:12:36 +0000643static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000646
Eric Andersen044228d2001-07-17 01:12:36 +0000647static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000648
Eric Andersen044228d2001-07-17 01:12:36 +0000649static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
Eric Andersen044228d2001-07-17 01:12:36 +0000651static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000652
653/* Architecture specific manipulation routines. */
654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000658
Eric Andersen044228d2001-07-17 01:12:36 +0000659static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000660
Eric Andersen044228d2001-07-17 01:12:36 +0000661static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000662 struct obj_section *targsec,
663 struct obj_section *symsec,
664 struct obj_symbol *sym,
665 ElfW(RelM) *rel, ElfW(Addr) value);
666
Eric Andersencffd5022002-05-24 06:50:15 +0000667static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000668
Glenn L McGrath759515c2003-08-30 06:00:33 +0000669static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000670
Eric Andersen9f16d612000-06-12 23:11:16 +0000671#endif /* obj.h */
672//----------------------------------------------------------------------------
673//--------end of modutils obj.h
674//----------------------------------------------------------------------------
675
676
Miles Baderae28b042002-04-01 09:34:25 +0000677/* SPFX is always a string, so it can be concatenated to string constants. */
678#ifdef SYMBOL_PREFIX
679#define SPFX SYMBOL_PREFIX
680#else
681#define SPFX ""
682#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000683
Erik Andersen02104321999-12-17 18:57:34 +0000684
Erik Andersend387d011999-12-21 02:55:11 +0000685#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000686static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000687
Eric Andersen9f16d612000-06-12 23:11:16 +0000688/*======================================================================*/
689
Eric Andersen044228d2001-07-17 01:12:36 +0000690static int flag_force_load = 0;
691static int flag_autoclean = 0;
692static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000693static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000694static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000695
696
697/*======================================================================*/
698
Eric Andersencffd5022002-05-24 06:50:15 +0000699#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000700
Eric Andersencffd5022002-05-24 06:50:15 +0000701struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000702{
Eric Andersencffd5022002-05-24 06:50:15 +0000703 struct arch_list_entry *next;
704 CONFIG_LIST_ARCHTYPE addend;
705 int offset;
706 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000707};
Eric Andersencffd5022002-05-24 06:50:15 +0000708
Eric Andersen21adca72000-12-06 18:18:26 +0000709#endif
710
Eric Andersencffd5022002-05-24 06:50:15 +0000711#if defined(CONFIG_USE_SINGLE)
712
713struct arch_single_entry
714{
Eric Andersen9f16d612000-06-12 23:11:16 +0000715 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000716 int inited : 1;
717 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000718};
Eric Andersencffd5022002-05-24 06:50:15 +0000719
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000720#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000721
Eric Andersen2bf658d2001-02-24 20:01:53 +0000722#if defined(__mips__)
723struct mips_hi16
724{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000725 struct mips_hi16 *next;
726 Elf32_Addr *addr;
727 Elf32_Addr value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000728};
729#endif
730
Eric Andersenfe4208f2000-09-24 03:44:29 +0000731struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000732 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000733#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000734 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000735#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000736#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000737 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000738#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000739#if defined(__mips__)
740 struct mips_hi16 *mips_hi16_list;
741#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000742};
743
Eric Andersenfe4208f2000-09-24 03:44:29 +0000744struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000745 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000746#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000747#if defined(CONFIG_USE_PLT_LIST)
748 struct arch_list_entry *pltent;
749#else
750 struct arch_single_entry pltent;
751#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000752#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000753#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000754 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000756};
757
758
Eric Andersen9f16d612000-06-12 23:11:16 +0000759struct external_module {
760 const char *name;
761 ElfW(Addr) addr;
762 int used;
763 size_t nsyms;
764 struct new_module_symbol *syms;
765};
766
Eric Andersen044228d2001-07-17 01:12:36 +0000767static struct new_module_symbol *ksyms;
768static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000769
Eric Andersen044228d2001-07-17 01:12:36 +0000770static struct external_module *ext_modules;
771static int n_ext_modules;
772static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000773extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000774
Eric Andersen61f83052002-06-22 17:15:42 +0000775static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000776static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000777
Eric Andersenfe4208f2000-09-24 03:44:29 +0000778
Erik Andersen02104321999-12-17 18:57:34 +0000779
Eric Andersen9f16d612000-06-12 23:11:16 +0000780/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000781
Eric Andersen9f16d612000-06-12 23:11:16 +0000782
Eric Andersen14d35432001-05-14 17:07:32 +0000783static int check_module_name_match(const char *filename, struct stat *statbuf,
784 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000785{
Eric Andersen14d35432001-05-14 17:07:32 +0000786 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000787
Eric Andersen14d35432001-05-14 17:07:32 +0000788 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000789 return (FALSE);
790 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000791 char *tmp, *tmp1 = bb_xstrdup(filename);
792 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000793 if (strcmp(tmp, fullname) == 0) {
794 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000795 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000796 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000797 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000798 }
Eric Andersen14d35432001-05-14 17:07:32 +0000799 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000800 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000801 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000802}
803
Erik Andersen02104321999-12-17 18:57:34 +0000804
Eric Andersen9f16d612000-06-12 23:11:16 +0000805/*======================================================================*/
806
Eric Andersen044228d2001-07-17 01:12:36 +0000807static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000808{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000809 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000810 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000811
Eric Andersencffd5022002-05-24 06:50:15 +0000812 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000813
Eric Andersen9f16d612000-06-12 23:11:16 +0000814 return &f->root;
815}
816
Eric Andersen044228d2001-07-17 01:12:36 +0000817static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000818{
819 return xmalloc(sizeof(struct obj_section));
820}
821
Eric Andersen044228d2001-07-17 01:12:36 +0000822static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000823{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000824 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000825 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000826
Eric Andersencffd5022002-05-24 06:50:15 +0000827 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828
Eric Andersen9f16d612000-06-12 23:11:16 +0000829 return &sym->root;
830}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000831
Eric Andersen044228d2001-07-17 01:12:36 +0000832static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000833arch_apply_relocation(struct obj_file *f,
834 struct obj_section *targsec,
835 struct obj_section *symsec,
836 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000837 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000838{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000839 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000840 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000841 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
842 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000843#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
844 struct arch_symbol *isym = (struct arch_symbol *) sym;
845#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000846#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000847 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000848#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000849#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000850 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000851 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000852#if defined(CONFIG_USE_PLT_LIST)
853 struct arch_list_entry *pe;
854#else
855 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000856#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000857#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000858
859 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000860
Eric Andersencffd5022002-05-24 06:50:15 +0000861
862#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000863 case R_ARM_NONE:
864 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000865
Eric Andersen3b1a7442003-12-24 20:30:45 +0000866 case R_ARM_ABS32:
867 *loc += v;
868 break;
Miles Baderae28b042002-04-01 09:34:25 +0000869
Eric Andersen3b1a7442003-12-24 20:30:45 +0000870 case R_ARM_GOT32:
871 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000872
Eric Andersen3b1a7442003-12-24 20:30:45 +0000873 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000874 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
875 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000876 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 assert(got);
879 *loc += got - dot;
880 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000881
Eric Andersen3b1a7442003-12-24 20:30:45 +0000882 case R_ARM_PC24:
883 case R_ARM_PLT32:
884 goto bb_use_plt;
885
886 case R_ARM_GOTOFF: /* address relative to the got */
887 assert(got);
888 *loc += v - got;
889 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000890
Eric Andersenbf77f612003-01-23 06:02:39 +0000891#elif defined(__s390__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 case R_390_32:
893 *(unsigned int *) loc += v;
894 break;
895 case R_390_16:
896 *(unsigned short *) loc += v;
897 break;
898 case R_390_8:
899 *(unsigned char *) loc += v;
900 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000901
Eric Andersen3b1a7442003-12-24 20:30:45 +0000902 case R_390_PC32:
903 *(unsigned int *) loc += v - dot;
904 break;
905 case R_390_PC16DBL:
906 *(unsigned short *) loc += (v - dot) >> 1;
907 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000908 case R_390_PC16:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000909 *(unsigned short *) loc += v - dot;
910 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000911
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 case R_390_PLT32:
913 case R_390_PLT16DBL:
914 /* find the plt entry and initialize it. */
915 assert(isym != NULL);
916 pe = (struct arch_single_entry *) &isym->pltent;
917 assert(pe->allocated);
918 if (pe->inited == 0) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000919 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000920 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
921 ip[1] = 0x100607f1;
922 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
923 ip[2] = v - 2;
924 else
925 ip[2] = v;
926 pe->inited = 1;
927 }
Eric Andersenbf77f612003-01-23 06:02:39 +0000928
Eric Andersen3b1a7442003-12-24 20:30:45 +0000929 /* Insert relative distance to target. */
930 v = plt + pe->offset - dot;
931 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
932 *(unsigned int *) loc = (unsigned int) v;
933 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
934 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
935 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000936
Eric Andersen3b1a7442003-12-24 20:30:45 +0000937 case R_390_GLOB_DAT:
938 case R_390_JMP_SLOT:
939 *loc = v;
940 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000941
Eric Andersen3b1a7442003-12-24 20:30:45 +0000942 case R_390_RELATIVE:
943 *loc += f->baseaddr;
944 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000945
Eric Andersen3b1a7442003-12-24 20:30:45 +0000946 case R_390_GOTPC:
947 assert(got != 0);
948 *(unsigned long *) loc += got - dot;
949 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000950
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 case R_390_GOT12:
952 case R_390_GOT16:
953 case R_390_GOT32:
954 assert(isym != NULL);
955 assert(got != 0);
956 if (!isym->gotent.inited)
957 {
958 isym->gotent.inited = 1;
959 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
960 }
961 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
962 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
963 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
964 *(unsigned short *) loc += isym->gotent.offset;
965 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
966 *(unsigned int *) loc += isym->gotent.offset;
967 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000968
Eric Andersen951df202003-10-21 06:45:29 +0000969#ifndef R_390_GOTOFF32
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000970#define R_390_GOTOFF32 R_390_GOTOFF
Eric Andersen951df202003-10-21 06:45:29 +0000971#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000972 case R_390_GOTOFF32:
973 assert(got != 0);
974 *loc += v - got;
975 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000976
Eric Andersencffd5022002-05-24 06:50:15 +0000977#elif defined(__i386__)
978
Eric Andersen3b1a7442003-12-24 20:30:45 +0000979 case R_386_NONE:
980 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000981
Eric Andersen3b1a7442003-12-24 20:30:45 +0000982 case R_386_32:
983 *loc += v;
984 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000985
Eric Andersen3b1a7442003-12-24 20:30:45 +0000986 case R_386_PLT32:
987 case R_386_PC32:
988 *loc += v - dot;
989 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000990
Eric Andersen3b1a7442003-12-24 20:30:45 +0000991 case R_386_GLOB_DAT:
992 case R_386_JMP_SLOT:
993 *loc = v;
994 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000995
Eric Andersen3b1a7442003-12-24 20:30:45 +0000996 case R_386_RELATIVE:
997 *loc += f->baseaddr;
998 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000999
Eric Andersen3b1a7442003-12-24 20:30:45 +00001000 case R_386_GOTPC:
1001 assert(got != 0);
1002 *loc += got - dot;
1003 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001004
Eric Andersen3b1a7442003-12-24 20:30:45 +00001005 case R_386_GOT32:
1006 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001007
Eric Andersen3b1a7442003-12-24 20:30:45 +00001008 case R_386_GOTOFF:
1009 assert(got != 0);
1010 *loc += v - got;
1011 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001012
1013#elif defined(__mc68000__)
1014
Eric Andersen3b1a7442003-12-24 20:30:45 +00001015 case R_68K_NONE:
1016 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001017
Eric Andersen3b1a7442003-12-24 20:30:45 +00001018 case R_68K_32:
1019 *loc += v;
1020 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001021
Eric Andersen3b1a7442003-12-24 20:30:45 +00001022 case R_68K_8:
1023 if (v > 0xff) {
1024 ret = obj_reloc_overflow;
1025 }
1026 *(char *)loc = v;
1027 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001028
Eric Andersen3b1a7442003-12-24 20:30:45 +00001029 case R_68K_16:
1030 if (v > 0xffff) {
1031 ret = obj_reloc_overflow;
1032 }
1033 *(short *)loc = v;
1034 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001035
Eric Andersen3b1a7442003-12-24 20:30:45 +00001036 case R_68K_PC8:
1037 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001038 if ((Elf32_Sword)v > 0x7f ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001039 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1040 ret = obj_reloc_overflow;
1041 }
1042 *(char *)loc = v;
1043 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001044
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_68K_PC16:
1046 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001047 if ((Elf32_Sword)v > 0x7fff ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001048 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1049 ret = obj_reloc_overflow;
1050 }
1051 *(short *)loc = v;
1052 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001053
Eric Andersen3b1a7442003-12-24 20:30:45 +00001054 case R_68K_PC32:
1055 *(int *)loc = v - dot;
1056 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001057
Eric Andersen3b1a7442003-12-24 20:30:45 +00001058 case R_68K_GLOB_DAT:
1059 case R_68K_JMP_SLOT:
1060 *loc = v;
1061 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001062
Eric Andersen3b1a7442003-12-24 20:30:45 +00001063 case R_68K_RELATIVE:
1064 *(int *)loc += f->baseaddr;
1065 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001066
Eric Andersen3b1a7442003-12-24 20:30:45 +00001067 case R_68K_GOT32:
1068 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001069
Eric Andersen16451a02004-03-19 12:16:18 +00001070#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001071 case R_68K_GOTOFF:
1072 assert(got != 0);
1073 *loc += v - got;
1074 break;
Eric Andersen16451a02004-03-19 12:16:18 +00001075#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001076
1077#elif defined(__mips__)
1078
Eric Andersen3b1a7442003-12-24 20:30:45 +00001079 case R_MIPS_NONE:
1080 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001081
Eric Andersen3b1a7442003-12-24 20:30:45 +00001082 case R_MIPS_32:
1083 *loc += v;
1084 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_MIPS_26:
1087 if (v % 4)
1088 ret = obj_reloc_dangerous;
1089 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1090 ret = obj_reloc_overflow;
1091 *loc =
1092 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1093 0x03ffffff);
1094 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001095
Eric Andersen3b1a7442003-12-24 20:30:45 +00001096 case R_MIPS_HI16:
1097 {
1098 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001099
Eric Andersen3b1a7442003-12-24 20:30:45 +00001100 /* We cannot relocate this one now because we don't know the value
1101 of the carry we need to add. Save the information, and let LO16
1102 do the actual relocation. */
1103 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1104 n->addr = loc;
1105 n->value = v;
1106 n->next = ifile->mips_hi16_list;
1107 ifile->mips_hi16_list = n;
1108 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001109 }
1110
Eric Andersen3b1a7442003-12-24 20:30:45 +00001111 case R_MIPS_LO16:
1112 {
1113 unsigned long insnlo = *loc;
1114 Elf32_Addr val, vallo;
1115
1116 /* Sign extend the addend we extract from the lo insn. */
1117 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1118
1119 if (ifile->mips_hi16_list != NULL) {
1120 struct mips_hi16 *l;
1121
1122 l = ifile->mips_hi16_list;
1123 while (l != NULL) {
1124 struct mips_hi16 *next;
1125 unsigned long insn;
1126
1127 /* The value for the HI16 had best be the same. */
1128 assert(v == l->value);
1129
1130 /* Do the HI16 relocation. Note that we actually don't
1131 need to know anything about the LO16 itself, except where
1132 to find the low 16 bits of the addend needed by the LO16. */
1133 insn = *l->addr;
1134 val =
1135 ((insn & 0xffff) << 16) +
1136 vallo;
1137 val += v;
1138
1139 /* Account for the sign extension that will happen in the
1140 low bits. */
1141 val =
1142 ((val >> 16) +
1143 ((val & 0x8000) !=
1144 0)) & 0xffff;
1145
1146 insn = (insn & ~0xffff) | val;
1147 *l->addr = insn;
1148
1149 next = l->next;
1150 free(l);
1151 l = next;
1152 }
1153
1154 ifile->mips_hi16_list = NULL;
1155 }
1156
1157 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1158 val = v + vallo;
1159 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1160 *loc = insnlo;
1161 break;
1162 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001163
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001164#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001165
Eric Andersen3b1a7442003-12-24 20:30:45 +00001166 case R_PPC_ADDR16_HA:
1167 *(unsigned short *)loc = (v + 0x8000) >> 16;
1168 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001169
Eric Andersen3b1a7442003-12-24 20:30:45 +00001170 case R_PPC_ADDR16_HI:
1171 *(unsigned short *)loc = v >> 16;
1172 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001173
Eric Andersen3b1a7442003-12-24 20:30:45 +00001174 case R_PPC_ADDR16_LO:
1175 *(unsigned short *)loc = v;
1176 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001177
Eric Andersen3b1a7442003-12-24 20:30:45 +00001178 case R_PPC_REL24:
1179 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001180
Eric Andersen3b1a7442003-12-24 20:30:45 +00001181 case R_PPC_REL32:
1182 *loc = v - dot;
1183 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001184
Eric Andersen3b1a7442003-12-24 20:30:45 +00001185 case R_PPC_ADDR32:
1186 *loc = v;
1187 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001188
1189#elif defined(__sh__)
1190
Eric Andersen3b1a7442003-12-24 20:30:45 +00001191 case R_SH_NONE:
1192 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001193
Eric Andersen3b1a7442003-12-24 20:30:45 +00001194 case R_SH_DIR32:
1195 *loc += v;
1196 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001197
Eric Andersen3b1a7442003-12-24 20:30:45 +00001198 case R_SH_REL32:
1199 *loc += v - dot;
1200 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001201
Eric Andersen3b1a7442003-12-24 20:30:45 +00001202 case R_SH_PLT32:
1203 *loc = v - dot;
1204 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001205
Eric Andersen3b1a7442003-12-24 20:30:45 +00001206 case R_SH_GLOB_DAT:
1207 case R_SH_JMP_SLOT:
1208 *loc = v;
1209 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001210
Eric Andersen3b1a7442003-12-24 20:30:45 +00001211 case R_SH_RELATIVE:
1212 *loc = f->baseaddr + rel->r_addend;
1213 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001214
Eric Andersen3b1a7442003-12-24 20:30:45 +00001215 case R_SH_GOTPC:
1216 assert(got != 0);
1217 *loc = got - dot + rel->r_addend;
1218 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001219
Eric Andersen3b1a7442003-12-24 20:30:45 +00001220 case R_SH_GOT32:
1221 goto bb_use_got;
1222
1223 case R_SH_GOTOFF:
1224 assert(got != 0);
1225 *loc = v - got;
1226 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001227
Eric Andersenbf833552003-08-13 19:56:33 +00001228#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001229 case R_SH_IMM_MEDLOW16:
1230 case R_SH_IMM_LOW16:
1231 {
1232 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001233
Eric Andersen3b1a7442003-12-24 20:30:45 +00001234 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1235 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001236
Eric Andersen3b1a7442003-12-24 20:30:45 +00001237 /*
1238 * movi and shori have the format:
1239 *
1240 * | op | imm | reg | reserved |
1241 * 31..26 25..10 9.. 4 3 .. 0
1242 *
1243 * so we simply mask and or in imm.
1244 */
1245 word = *loc & ~0x3fffc00;
1246 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001247
Eric Andersen3b1a7442003-12-24 20:30:45 +00001248 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001249
Eric Andersen3b1a7442003-12-24 20:30:45 +00001250 break;
1251 }
Eric Andersenbf833552003-08-13 19:56:33 +00001252
Eric Andersen3b1a7442003-12-24 20:30:45 +00001253 case R_SH_IMM_MEDLOW16_PCREL:
1254 case R_SH_IMM_LOW16_PCREL:
1255 {
1256 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001257
Eric Andersen3b1a7442003-12-24 20:30:45 +00001258 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001259
Eric Andersen3b1a7442003-12-24 20:30:45 +00001260 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001261
Eric Andersen3b1a7442003-12-24 20:30:45 +00001262 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1263 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001264
Eric Andersen3b1a7442003-12-24 20:30:45 +00001265 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001266
Eric Andersen3b1a7442003-12-24 20:30:45 +00001267 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001268
Eric Andersen3b1a7442003-12-24 20:30:45 +00001269 break;
1270 }
Eric Andersenbf833552003-08-13 19:56:33 +00001271#endif /* __SH5__ */
1272#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001273
Eric Andersen3b1a7442003-12-24 20:30:45 +00001274 default:
1275 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1276 ret = obj_reloc_unhandled;
1277 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001278
1279#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001280 case R_V850_NONE:
1281 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001282
Eric Andersen3b1a7442003-12-24 20:30:45 +00001283 case R_V850_32:
1284 /* We write two shorts instead of a long because even
1285 32-bit insns only need half-word alignment, but
1286 32-bit data needs to be long-word aligned. */
1287 v += ((unsigned short *)loc)[0];
1288 v += ((unsigned short *)loc)[1] << 16;
1289 ((unsigned short *)loc)[0] = v & 0xffff;
1290 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1291 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001292
Eric Andersen3b1a7442003-12-24 20:30:45 +00001293 case R_V850_22_PCREL:
1294 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001295#endif
1296
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001297#if defined (__cris__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001298 case R_CRIS_NONE:
1299 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001300
Eric Andersen3b1a7442003-12-24 20:30:45 +00001301 case R_CRIS_32:
1302 /* CRIS keeps the relocation value in the r_addend field and
1303 * should not use whats in *loc at all
1304 */
1305 *loc = v;
1306 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001307#endif
1308
Eric Andersena6f6a952004-05-26 12:06:38 +00001309#if defined(__H8300H__) || defined(__H8300S__)
Eric Andersenee70fa52004-05-26 11:38:46 +00001310 case R_H8_DIR24R8:
1311 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
1312 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
1313 break;
1314 case R_H8_DIR24A8:
1315 *loc += v;
1316 break;
1317 case R_H8_DIR32:
1318 case R_H8_DIR32A16:
1319 *loc += v;
1320 break;
1321 case R_H8_PCREL16:
1322 v -= dot + 2;
1323 if ((Elf32_Sword)v > 0x7fff ||
1324 (Elf32_Sword)v < -(Elf32_Sword)0x8000)
1325 ret = obj_reloc_overflow;
1326 else
1327 *(unsigned short *)loc = v;
1328 break;
1329 case R_H8_PCREL8:
1330 v -= dot + 1;
1331 if ((Elf32_Sword)v > 0x7f ||
1332 (Elf32_Sword)v < -(Elf32_Sword)0x80)
1333 ret = obj_reloc_overflow;
1334 else
1335 *(unsigned char *)loc = v;
1336 break;
1337#endif
1338
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001339#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001340
Eric Andersen3b1a7442003-12-24 20:30:45 +00001341bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001342
Eric Andersen3b1a7442003-12-24 20:30:45 +00001343 /* find the plt entry and initialize it if necessary */
1344 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001345
Eric Andersencffd5022002-05-24 06:50:15 +00001346#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001347 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1348 pe = pe->next;
1349 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001350#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001351 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001352#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001353
Eric Andersen3b1a7442003-12-24 20:30:45 +00001354 if (! pe->inited) {
1355 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001356
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001358
1359#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001360 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1361 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001362#endif
1363#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001364 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1365 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1366 ip[2] = 0x7d6903a6; /* mtctr r11 */
1367 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001368#endif
Miles Baderae28b042002-04-01 09:34:25 +00001369#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001370 /* We have to trash a register, so we assume that any control
1371 transfer more than 21-bits away must be a function call
1372 (so we can use a call-clobbered register). */
1373 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1374 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001375#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001376 pe->inited = 1;
1377 }
Eric Andersen21adca72000-12-06 18:18:26 +00001378
Eric Andersen3b1a7442003-12-24 20:30:45 +00001379 /* relative distance to target */
1380 v -= dot;
1381 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001382#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001383 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001384#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001385 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001386#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001387 /* go via the plt */
1388 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001389
1390#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001391 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001392#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001393 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001394#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001395 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001396
Eric Andersen3b1a7442003-12-24 20:30:45 +00001397 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001398#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001399 /* Convert to words. */
1400 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001401
Eric Andersen3b1a7442003-12-24 20:30:45 +00001402 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001403#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001404#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001405 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001406#endif
Miles Baderae28b042002-04-01 09:34:25 +00001407#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001408 /* We write two shorts instead of a long because even 32-bit insns
1409 only need half-word alignment, but the 32-bit data write needs
1410 to be long-word aligned. */
1411 ((unsigned short *)loc)[0] =
1412 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1413 | ((v >> 16) & 0x3f); /* offs high part */
1414 ((unsigned short *)loc)[1] =
1415 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001416#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001417 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001418#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001419
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001420#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001421bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001422
Eric Andersen3b1a7442003-12-24 20:30:45 +00001423 assert(isym != NULL);
1424 /* needs an entry in the .got: set it, once */
1425 if (!isym->gotent.inited) {
1426 isym->gotent.inited = 1;
1427 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1428 }
1429 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001430#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001431 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001432#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001433 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001434#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001435 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001436
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001437#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001438 }
1439
1440 return ret;
1441}
1442
Eric Andersencffd5022002-05-24 06:50:15 +00001443
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001444#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001445
1446static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1447 int offset, int size)
1448{
1449 struct arch_list_entry *pe;
1450
1451 for (pe = *list; pe != NULL; pe = pe->next) {
1452 if (pe->addend == rel->r_addend) {
1453 break;
1454 }
1455 }
1456
1457 if (pe == NULL) {
1458 pe = xmalloc(sizeof(struct arch_list_entry));
1459 pe->next = *list;
1460 pe->addend = rel->r_addend;
1461 pe->offset = offset;
1462 pe->inited = 0;
1463 *list = pe;
1464 return size;
1465 }
1466 return 0;
1467}
1468
1469#endif
1470
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001471#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001472
1473static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1474 int offset, int size)
1475{
1476 if (single->allocated == 0) {
1477 single->allocated = 1;
1478 single->offset = offset;
1479 single->inited = 0;
1480 return size;
1481 }
1482 return 0;
1483}
1484
1485#endif
1486
1487#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1488
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001489static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001490 int offset, int size)
1491{
1492 struct obj_section *myrelsec = obj_find_section(f, name);
1493
1494 if (offset == 0) {
1495 offset += size;
1496 }
1497
1498 if (myrelsec) {
1499 obj_extend_section(myrelsec, offset);
1500 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001501 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001502 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001503 assert(myrelsec);
1504 }
1505
1506 return myrelsec;
1507}
1508
1509#endif
1510
1511static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001512{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001513#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001514 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001515 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001516#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001517 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001518#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001519#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001520 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001521#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001522 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001523 ElfW(RelM) *rel, *relend;
1524 ElfW(Sym) *symtab, *extsym;
1525 const char *strtab, *name;
1526 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001527
Eric Andersen21adca72000-12-06 18:18:26 +00001528 for (i = 0; i < f->header.e_shnum; ++i) {
1529 relsec = f->sections[i];
1530 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001531 continue;
1532
Eric Andersen21adca72000-12-06 18:18:26 +00001533 symsec = f->sections[relsec->header.sh_link];
1534 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001535
Eric Andersen21adca72000-12-06 18:18:26 +00001536 rel = (ElfW(RelM) *) relsec->contents;
1537 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1538 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001539 strtab = (const char *) strsec->contents;
1540
1541 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001542 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001543
Eric Andersencffd5022002-05-24 06:50:15 +00001544#if defined(CONFIG_USE_GOT_ENTRIES)
1545 got_allocate = 0;
1546#endif
1547#if defined(CONFIG_USE_PLT_ENTRIES)
1548 plt_allocate = 0;
1549#endif
1550
Eric Andersen9f16d612000-06-12 23:11:16 +00001551 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001552#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001553 case R_ARM_PC24:
1554 case R_ARM_PLT32:
1555 plt_allocate = 1;
1556 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001557
Eric Andersen3b1a7442003-12-24 20:30:45 +00001558 case R_ARM_GOTOFF:
1559 case R_ARM_GOTPC:
1560 got_needed = 1;
1561 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001562
Eric Andersen3b1a7442003-12-24 20:30:45 +00001563 case R_ARM_GOT32:
1564 got_allocate = 1;
1565 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001566
Eric Andersen21adca72000-12-06 18:18:26 +00001567#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001568 case R_386_GOTPC:
1569 case R_386_GOTOFF:
1570 got_needed = 1;
1571 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001572
Eric Andersen3b1a7442003-12-24 20:30:45 +00001573 case R_386_GOT32:
1574 got_allocate = 1;
1575 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001576
1577#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001578 case R_PPC_REL24:
1579 plt_allocate = 1;
1580 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001581
1582#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001583 case R_68K_GOT32:
1584 got_allocate = 1;
1585 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001586
Eric Andersen16451a02004-03-19 12:16:18 +00001587#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001588 case R_68K_GOTOFF:
1589 got_needed = 1;
1590 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001591#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001592
1593#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001594 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001595 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001596 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001597
Eric Andersen3b1a7442003-12-24 20:30:45 +00001598 case R_SH_GOTPC:
1599 case R_SH_GOTOFF:
1600 got_needed = 1;
1601 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001602
1603#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001604 case R_V850_22_PCREL:
1605 plt_needed = 1;
1606 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001607
1608#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001609 default:
1610 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001611 }
1612
Eric Andersen21adca72000-12-06 18:18:26 +00001613 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001614 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001615 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001616 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001617 }
1618 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001619#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001620 if (got_allocate) {
1621 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001622 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001623 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001624
1625 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001626 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001627#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001628#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001629 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001630#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001631 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001632 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001634#else
1635 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001636 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001637 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001638#endif
1639 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001640 }
1641#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001642 }
Miles Baderae28b042002-04-01 09:34:25 +00001643 }
Eric Andersen21adca72000-12-06 18:18:26 +00001644
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001645#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001646 if (got_needed) {
1647 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001649 }
Eric Andersen21adca72000-12-06 18:18:26 +00001650#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001651
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001652#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001653 if (plt_needed) {
1654 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001656 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001658
1659#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001660}
1661
Eric Andersen9f16d612000-06-12 23:11:16 +00001662/*======================================================================*/
1663
1664/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001665static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001666{
1667 unsigned long h = 0;
1668 unsigned long g;
1669 unsigned char ch;
1670
1671 while (n > 0) {
1672 ch = *name++;
1673 h = (h << 4) + ch;
1674 if ((g = (h & 0xf0000000)) != 0) {
1675 h ^= g >> 24;
1676 h &= ~g;
1677 }
1678 n--;
1679 }
1680 return h;
1681}
1682
Eric Andersen044228d2001-07-17 01:12:36 +00001683static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001684{
1685 return obj_elf_hash_n(name, strlen(name));
1686}
1687
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001688#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001689/* String comparison for non-co-versioned kernel and module. */
1690
1691static int ncv_strcmp(const char *a, const char *b)
1692{
1693 size_t alen = strlen(a), blen = strlen(b);
1694
1695 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1696 return strncmp(a, b, alen);
1697 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1698 return strncmp(a, b, blen);
1699 else
1700 return strcmp(a, b);
1701}
1702
1703/* String hashing for non-co-versioned kernel and module. Here
1704 we are simply forced to drop the crc from the hash. */
1705
1706static unsigned long ncv_symbol_hash(const char *str)
1707{
1708 size_t len = strlen(str);
1709 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1710 len -= 10;
1711 return obj_elf_hash_n(str, len);
1712}
1713
Eric Andersen044228d2001-07-17 01:12:36 +00001714static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001715obj_set_symbol_compare(struct obj_file *f,
1716 int (*cmp) (const char *, const char *),
1717 unsigned long (*hash) (const char *))
1718{
1719 if (cmp)
1720 f->symbol_cmp = cmp;
1721 if (hash) {
1722 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1723 int i;
1724
1725 f->symbol_hash = hash;
1726
1727 memcpy(tmptab, f->symtab, sizeof(tmptab));
1728 memset(f->symtab, 0, sizeof(f->symtab));
1729
1730 for (i = 0; i < HASH_BUCKETS; ++i)
1731 for (sym = tmptab[i]; sym; sym = next) {
1732 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1733 next = sym->next;
1734 sym->next = f->symtab[h];
1735 f->symtab[h] = sym;
1736 }
1737 }
1738}
1739
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001740#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001741
Eric Andersen044228d2001-07-17 01:12:36 +00001742static struct obj_symbol *
1743obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001744 unsigned long symidx, int info,
1745 int secidx, ElfW(Addr) value,
1746 unsigned long size)
1747{
1748 struct obj_symbol *sym;
1749 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1750 int n_type = ELFW(ST_TYPE) (info);
1751 int n_binding = ELFW(ST_BIND) (info);
1752
1753 for (sym = f->symtab[hash]; sym; sym = sym->next)
1754 if (f->symbol_cmp(sym->name, name) == 0) {
1755 int o_secidx = sym->secidx;
1756 int o_info = sym->info;
1757 int o_type = ELFW(ST_TYPE) (o_info);
1758 int o_binding = ELFW(ST_BIND) (o_info);
1759
1760 /* A redefinition! Is it legal? */
1761
1762 if (secidx == SHN_UNDEF)
1763 return sym;
1764 else if (o_secidx == SHN_UNDEF)
1765 goto found;
1766 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1767 /* Cope with local and global symbols of the same name
1768 in the same object file, as might have been created
1769 by ld -r. The only reason locals are now seen at this
1770 level at all is so that we can do semi-sensible things
1771 with parameters. */
1772
1773 struct obj_symbol *nsym, **p;
1774
1775 nsym = arch_new_symbol();
1776 nsym->next = sym->next;
1777 nsym->ksymidx = -1;
1778
1779 /* Excise the old (local) symbol from the hash chain. */
1780 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1781 continue;
1782 *p = sym = nsym;
1783 goto found;
1784 } else if (n_binding == STB_LOCAL) {
1785 /* Another symbol of the same name has already been defined.
1786 Just add this to the local table. */
1787 sym = arch_new_symbol();
1788 sym->next = NULL;
1789 sym->ksymidx = -1;
1790 f->local_symtab[symidx] = sym;
1791 goto found;
1792 } else if (n_binding == STB_WEAK)
1793 return sym;
1794 else if (o_binding == STB_WEAK)
1795 goto found;
1796 /* Don't unify COMMON symbols with object types the programmer
1797 doesn't expect. */
1798 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001799 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001800 return sym;
1801 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001802 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001803 goto found;
1804 else {
1805 /* Don't report an error if the symbol is coming from
1806 the kernel or some external module. */
1807 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001808 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001809 return sym;
1810 }
1811 }
1812
1813 /* Completely new symbol. */
1814 sym = arch_new_symbol();
1815 sym->next = f->symtab[hash];
1816 f->symtab[hash] = sym;
1817 sym->ksymidx = -1;
1818
Eric Andersen66ca9482001-06-28 21:36:06 +00001819 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1820 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001821 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001822 name, (long) symidx, (long) f->local_symtab_size);
1823 else
1824 f->local_symtab[symidx] = sym;
1825 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001826
Eric Andersen3b1a7442003-12-24 20:30:45 +00001827found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001828 sym->name = name;
1829 sym->value = value;
1830 sym->size = size;
1831 sym->secidx = secidx;
1832 sym->info = info;
1833
1834 return sym;
1835}
1836
Eric Andersen044228d2001-07-17 01:12:36 +00001837static struct obj_symbol *
1838obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001839{
1840 struct obj_symbol *sym;
1841 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1842
1843 for (sym = f->symtab[hash]; sym; sym = sym->next)
1844 if (f->symbol_cmp(sym->name, name) == 0)
1845 return sym;
1846
1847 return NULL;
1848}
1849
Eric Andersen044228d2001-07-17 01:12:36 +00001850static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001851 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1852{
1853 if (sym) {
1854 if (sym->secidx >= SHN_LORESERVE)
1855 return sym->value;
1856
1857 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1858 } else {
1859 /* As a special case, a NULL sym has value zero. */
1860 return 0;
1861 }
1862}
1863
Eric Andersen044228d2001-07-17 01:12:36 +00001864static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001865{
1866 int i, n = f->header.e_shnum;
1867
1868 for (i = 0; i < n; ++i)
1869 if (strcmp(f->sections[i]->name, name) == 0)
1870 return f->sections[i];
1871
1872 return NULL;
1873}
1874
1875static int obj_load_order_prio(struct obj_section *a)
1876{
1877 unsigned long af, ac;
1878
1879 af = a->header.sh_flags;
1880
1881 ac = 0;
1882 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001883 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001884 ac |= 32;
1885 if (af & SHF_ALLOC)
1886 ac |= 16;
1887 if (!(af & SHF_WRITE))
1888 ac |= 8;
1889 if (af & SHF_EXECINSTR)
1890 ac |= 4;
1891 if (a->header.sh_type != SHT_NOBITS)
1892 ac |= 2;
1893
1894 return ac;
1895}
1896
Eric Andersen044228d2001-07-17 01:12:36 +00001897static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001898obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1899{
1900 struct obj_section **p;
1901 int prio = obj_load_order_prio(sec);
1902 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1903 if (obj_load_order_prio(*p) < prio)
1904 break;
1905 sec->load_next = *p;
1906 *p = sec;
1907}
1908
Eric Andersen044228d2001-07-17 01:12:36 +00001909static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001910 const char *name,
1911 unsigned long align,
1912 unsigned long size)
1913{
1914 int newidx = f->header.e_shnum++;
1915 struct obj_section *sec;
1916
1917 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1918 f->sections[newidx] = sec = arch_new_section();
1919
1920 memset(sec, 0, sizeof(*sec));
1921 sec->header.sh_type = SHT_PROGBITS;
1922 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1923 sec->header.sh_size = size;
1924 sec->header.sh_addralign = align;
1925 sec->name = name;
1926 sec->idx = newidx;
1927 if (size)
1928 sec->contents = xmalloc(size);
1929
1930 obj_insert_section_load_order(f, sec);
1931
1932 return sec;
1933}
1934
Eric Andersen044228d2001-07-17 01:12:36 +00001935static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001936 const char *name,
1937 unsigned long align,
1938 unsigned long size)
1939{
1940 int newidx = f->header.e_shnum++;
1941 struct obj_section *sec;
1942
1943 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1944 f->sections[newidx] = sec = arch_new_section();
1945
1946 memset(sec, 0, sizeof(*sec));
1947 sec->header.sh_type = SHT_PROGBITS;
1948 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1949 sec->header.sh_size = size;
1950 sec->header.sh_addralign = align;
1951 sec->name = name;
1952 sec->idx = newidx;
1953 if (size)
1954 sec->contents = xmalloc(size);
1955
1956 sec->load_next = f->load_order;
1957 f->load_order = sec;
1958 if (f->load_order_search_start == &f->load_order)
1959 f->load_order_search_start = &sec->load_next;
1960
1961 return sec;
1962}
1963
Eric Andersen044228d2001-07-17 01:12:36 +00001964static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001965{
1966 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001967 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001968 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1969 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001970 return sec->contents + oldsize;
1971}
1972
1973
Eric Andersen9f16d612000-06-12 23:11:16 +00001974/* Conditionally add the symbols from the given symbol set to the
1975 new module. */
1976
1977static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00001978add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001979 int idx, struct new_module_symbol *syms, size_t nsyms)
1980{
1981 struct new_module_symbol *s;
1982 size_t i;
1983 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001984#ifdef SYMBOL_PREFIX
1985 char *name_buf = 0;
1986 size_t name_alloced_size = 0;
1987#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001988#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
1989 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00001990
Glenn L McGrath759515c2003-08-30 06:00:33 +00001991 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001992#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001993 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001994 /* Only add symbols that are already marked external.
1995 If we override locals we may cause problems for
1996 argument initialization. We will also create a false
1997 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001998 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001999 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002000
Glenn L McGrath759515c2003-08-30 06:00:33 +00002001 /* GPL licensed modules can use symbols exported with
2002 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2003 * exported names. Non-GPL modules never see any GPLONLY_
2004 * symbols so they cannot fudge it by adding the prefix on
2005 * their references.
2006 */
2007 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002008#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002009 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002010 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002011 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002012#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002013 continue;
2014 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002015 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002016
Miles Baderae28b042002-04-01 09:34:25 +00002017#ifdef SYMBOL_PREFIX
2018 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2019 kernel exports `C names', but module object files
2020 reference `linker names'). */
2021 size_t extra = sizeof SYMBOL_PREFIX;
2022 size_t name_size = strlen (name) + extra;
2023 if (name_size > name_alloced_size) {
2024 name_alloced_size = name_size * 2;
2025 name_buf = alloca (name_alloced_size);
2026 }
2027 strcpy (name_buf, SYMBOL_PREFIX);
2028 strcpy (name_buf + extra - 1, name);
2029 name = name_buf;
2030#endif /* SYMBOL_PREFIX */
2031
2032 sym = obj_find_symbol(f, name);
2033 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
2034#ifdef SYMBOL_PREFIX
2035 /* Put NAME_BUF into more permanent storage. */
2036 name = xmalloc (name_size);
2037 strcpy (name, name_buf);
2038#endif
2039 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002040 ELFW(ST_INFO) (STB_GLOBAL,
2041 STT_NOTYPE),
2042 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002043 /* Did our symbol just get installed? If so, mark the
2044 module as "used". */
2045 if (sym->secidx == idx)
2046 used = 1;
2047 }
2048 }
2049
2050 return used;
2051}
2052
2053static void add_kernel_symbols(struct obj_file *f)
2054{
2055 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002056 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002057
2058 /* Add module symbols first. */
2059
2060 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2061 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002062 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2063 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002064
2065 n_ext_modules_used = nused;
2066
2067 /* And finally the symbols from the kernel proper. */
2068
2069 if (nksyms)
2070 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2071}
2072
2073static char *get_modinfo_value(struct obj_file *f, const char *key)
2074{
2075 struct obj_section *sec;
2076 char *p, *v, *n, *ep;
2077 size_t klen = strlen(key);
2078
2079 sec = obj_find_section(f, ".modinfo");
2080 if (sec == NULL)
2081 return NULL;
2082 p = sec->contents;
2083 ep = p + sec->header.sh_size;
2084 while (p < ep) {
2085 v = strchr(p, '=');
2086 n = strchr(p, '\0');
2087 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002088 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002089 return v + 1;
2090 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002091 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002092 return n;
2093 }
2094 p = n + 1;
2095 }
2096
2097 return NULL;
2098}
2099
2100
2101/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002102/* Functions relating to module loading after 2.1.18. */
2103
2104static int
2105new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2106{
2107 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002108 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002109 struct obj_symbol *sym;
2110 char *contents, *loc;
2111 int min, max, n;
2112
2113 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002114 if ((q = strchr(p, '=')) == NULL) {
2115 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002116 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002117 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002118
2119 key = alloca(q - p + 6);
2120 memcpy(key, "parm_", 5);
2121 memcpy(key + 5, p, q - p);
2122 key[q - p + 5] = 0;
2123
2124 p = get_modinfo_value(f, key);
2125 key += 5;
2126 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002127 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002128 return 0;
2129 }
2130
Miles Baderae28b042002-04-01 09:34:25 +00002131#ifdef SYMBOL_PREFIX
2132 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2133 strcpy (sym_name, SYMBOL_PREFIX);
2134 strcat (sym_name, key);
2135#else
2136 sym_name = key;
2137#endif
2138 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002139
2140 /* Also check that the parameter was not resolved from the kernel. */
2141 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002142 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002143 return 0;
2144 }
2145
2146 if (isdigit(*p)) {
2147 min = strtoul(p, &p, 10);
2148 if (*p == '-')
2149 max = strtoul(p + 1, &p, 10);
2150 else
2151 max = min;
2152 } else
2153 min = max = 1;
2154
2155 contents = f->sections[sym->secidx]->contents;
2156 loc = contents + sym->value;
2157 n = (*++q != '\0');
2158
2159 while (1) {
2160 if ((*p == 's') || (*p == 'c')) {
2161 char *str;
2162
2163 /* Do C quoting if we begin with a ", else slurp the lot. */
2164 if (*q == '"') {
2165 char *r;
2166
2167 str = alloca(strlen(q));
2168 for (r = str, q++; *q != '"'; ++q, ++r) {
2169 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002170 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002171 key);
2172 return 0;
2173 } else if (*q == '\\')
2174 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002175 case 'a':
2176 *r = '\a';
2177 break;
2178 case 'b':
2179 *r = '\b';
2180 break;
2181 case 'e':
2182 *r = '\033';
2183 break;
2184 case 'f':
2185 *r = '\f';
2186 break;
2187 case 'n':
2188 *r = '\n';
2189 break;
2190 case 'r':
2191 *r = '\r';
2192 break;
2193 case 't':
2194 *r = '\t';
2195 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002196
Eric Andersen3b1a7442003-12-24 20:30:45 +00002197 case '0':
2198 case '1':
2199 case '2':
2200 case '3':
2201 case '4':
2202 case '5':
2203 case '6':
2204 case '7':
2205 {
2206 int c = *q - '0';
2207 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002208 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002209 if (q[1] >= '0' && q[1] <= '7')
2210 c = (c * 8) + *++q - '0';
2211 }
2212 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002213 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002214 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002215
Eric Andersen3b1a7442003-12-24 20:30:45 +00002216 default:
2217 *r = *q;
2218 break;
2219 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002220 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002221 }
2222 *r = '\0';
2223 ++q;
2224 } else {
2225 char *r;
2226
2227 /* In this case, the string is not quoted. We will break
2228 it using the coma (like for ints). If the user wants to
2229 include comas in a string, he just has to quote it */
2230
2231 /* Search the next coma */
2232 r = strchr(q, ',');
2233
2234 /* Found ? */
2235 if (r != (char *) NULL) {
2236 /* Recopy the current field */
2237 str = alloca(r - q + 1);
2238 memcpy(str, q, r - q);
2239
Eric Andersenaff114c2004-04-14 17:51:38 +00002240 /* I don't know if it is useful, as the previous case
2241 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002242 str[r - q] = '\0';
2243
2244 /* Keep next fields */
2245 q = r;
2246 } else {
2247 /* last string */
2248 str = q;
2249 q = "";
2250 }
2251 }
2252
2253 if (*p == 's') {
2254 /* Normal string */
2255 obj_string_patch(f, sym->secidx, loc - contents, str);
2256 loc += tgt_sizeof_char_p;
2257 } else {
2258 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002259 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002260
2261 /* Get the size of each member */
2262 /* Probably we should do that outside the loop ? */
2263 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002264 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002265 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002266 return 0;
2267 }
2268 charssize = strtoul(p + 1, (char **) NULL, 10);
2269
2270 /* Check length */
2271 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002272 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002273 charssize - 1);
2274 return 0;
2275 }
2276
2277 /* Copy to location */
2278 strcpy((char *) loc, str);
2279 loc += charssize;
2280 }
2281 } else {
2282 long v = strtoul(q, &q, 0);
2283 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002284 case 'b':
2285 *loc++ = v;
2286 break;
2287 case 'h':
2288 *(short *) loc = v;
2289 loc += tgt_sizeof_short;
2290 break;
2291 case 'i':
2292 *(int *) loc = v;
2293 loc += tgt_sizeof_int;
2294 break;
2295 case 'l':
2296 *(long *) loc = v;
2297 loc += tgt_sizeof_long;
2298 break;
2299
2300 default:
2301 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2302 return 0;
2303 }
2304 }
2305
2306retry_end_of_value:
2307 switch (*q) {
2308 case '\0':
2309 goto end_of_arg;
2310
2311 case ' ':
2312 case '\t':
2313 case '\n':
2314 case '\r':
2315 ++q;
2316 goto retry_end_of_value;
2317
2318 case ',':
2319 if (++n > max) {
2320 bb_error_msg("too many values for %s (max %d)", key, max);
2321 return 0;
2322 }
2323 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002324 break;
2325
2326 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002327 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002328 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002329 }
2330 }
2331
Eric Andersen3b1a7442003-12-24 20:30:45 +00002332end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002333 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002334 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002335 return 0;
2336 }
2337
2338 argc--, argv++;
2339 }
2340
2341 return 1;
2342}
2343
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002344#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002345static int new_is_module_checksummed(struct obj_file *f)
2346{
2347 const char *p = get_modinfo_value(f, "using_checksums");
2348 if (p)
2349 return atoi(p);
2350 else
2351 return 0;
2352}
2353
2354/* Get the module's kernel version in the canonical integer form. */
2355
2356static int
2357new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2358{
2359 char *p, *q;
2360 int a, b, c;
2361
2362 p = get_modinfo_value(f, "kernel_version");
2363 if (p == NULL)
2364 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002365 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002366
2367 a = strtoul(p, &p, 10);
2368 if (*p != '.')
2369 return -1;
2370 b = strtoul(p + 1, &p, 10);
2371 if (*p != '.')
2372 return -1;
2373 c = strtoul(p + 1, &q, 10);
2374 if (p + 1 == q)
2375 return -1;
2376
2377 return a << 16 | b << 8 | c;
2378}
2379
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002380#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002381
2382
Eric Andersen9f16d612000-06-12 23:11:16 +00002383/* Fetch the loaded modules, and all currently exported symbols. */
2384
2385static int new_get_kernel_symbols(void)
2386{
2387 char *module_names, *mn;
2388 struct external_module *modules, *m;
2389 struct new_module_symbol *syms, *s;
2390 size_t ret, bufsize, nmod, nsyms, i, j;
2391
2392 /* Collect the loaded modules. */
2393
2394 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002395retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002396 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002397 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002398 module_names = xrealloc(module_names, bufsize = ret);
2399 goto retry_modules_load;
2400 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002401 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002402 return 0;
2403 }
2404
2405 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002406
2407 /* Collect the modules' symbols. */
2408
Mark Whitley94fd4802001-03-12 23:08:34 +00002409 if (nmod){
2410 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2411 memset(modules, 0, nmod * sizeof(*modules));
2412 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002413 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002414 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002415
Mark Whitley94fd4802001-03-12 23:08:34 +00002416 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2417 if (errno == ENOENT) {
2418 /* The module was removed out from underneath us. */
2419 continue;
2420 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002421 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002422 return 0;
2423 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002424
Mark Whitley94fd4802001-03-12 23:08:34 +00002425 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002426retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002427 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2428 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002429 case ENOSPC:
2430 syms = xrealloc(syms, bufsize = ret);
2431 goto retry_mod_sym_load;
2432 case ENOENT:
2433 /* The module was removed out from underneath us. */
2434 continue;
2435 default:
2436 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2437 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002438 }
2439 }
2440 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002441
Mark Whitley94fd4802001-03-12 23:08:34 +00002442 m->name = mn;
2443 m->addr = info.addr;
2444 m->nsyms = nsyms;
2445 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002446
Mark Whitley94fd4802001-03-12 23:08:34 +00002447 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2448 s->name += (unsigned long) syms;
2449 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002450 }
2451 }
2452
2453 /* Collect the kernel's symbols. */
2454
2455 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002456retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002457 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002458 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002459 syms = xrealloc(syms, bufsize = ret);
2460 goto retry_kern_sym_load;
2461 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002462 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002463 return 0;
2464 }
2465 nksyms = nsyms = ret;
2466 ksyms = syms;
2467
2468 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2469 s->name += (unsigned long) syms;
2470 }
2471 return 1;
2472}
2473
2474
2475/* Return the kernel symbol checksum version, or zero if not used. */
2476
2477static int new_is_kernel_checksummed(void)
2478{
2479 struct new_module_symbol *s;
2480 size_t i;
2481
2482 /* Using_Versions is not the first symbol, but it should be in there. */
2483
2484 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2485 if (strcmp((char *) s->name, "Using_Versions") == 0)
2486 return s->value;
2487
2488 return 0;
2489}
2490
2491
2492static int new_create_this_module(struct obj_file *f, const char *m_name)
2493{
2494 struct obj_section *sec;
2495
2496 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002497 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002498 memset(sec->contents, 0, sizeof(struct new_module));
2499
Miles Baderae28b042002-04-01 09:34:25 +00002500 obj_add_symbol(f, SPFX "__this_module", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002501 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2502 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002503
2504 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002505 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002506
2507 return 1;
2508}
2509
Eric Andersen889dd202003-01-23 04:48:34 +00002510#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2511/* add an entry to the __ksymtab section, creating it if necessary */
2512static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2513{
2514 struct obj_section *sec;
2515 ElfW(Addr) ofs;
2516
2517 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2518 * If __ksymtab is defined but not marked alloc, x out the first character
2519 * (no obj_delete routine) and create a new __ksymtab with the correct
2520 * characteristics.
2521 */
2522 sec = obj_find_section(f, "__ksymtab");
2523 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2524 *((char *)(sec->name)) = 'x'; /* override const */
2525 sec = NULL;
2526 }
2527 if (!sec)
2528 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002529 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002530 if (!sec)
2531 return;
2532 sec->header.sh_flags |= SHF_ALLOC;
2533 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002534 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002535 ofs = sec->header.sh_size;
2536 obj_symbol_patch(f, sec->idx, ofs, sym);
2537 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2538 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2539}
2540#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002541
2542static int new_create_module_ksymtab(struct obj_file *f)
2543{
2544 struct obj_section *sec;
2545 int i;
2546
2547 /* We must always add the module references. */
2548
2549 if (n_ext_modules_used) {
2550 struct new_module_ref *dep;
2551 struct obj_symbol *tm;
2552
2553 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002554 (sizeof(struct new_module_ref)
2555 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002556 if (!sec)
2557 return 0;
2558
Miles Baderae28b042002-04-01 09:34:25 +00002559 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 dep = (struct new_module_ref *) sec->contents;
2561 for (i = 0; i < n_ext_modules; ++i)
2562 if (ext_modules[i].used) {
2563 dep->dep = ext_modules[i].addr;
2564 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002565 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002566 dep->next_ref = 0;
2567 ++dep;
2568 }
2569 }
2570
2571 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2572 size_t nsyms;
2573 int *loaded;
2574
2575 sec =
2576 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002577 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002578
2579 /* We don't want to export symbols residing in sections that
2580 aren't loaded. There are a number of these created so that
2581 we make sure certain module options don't appear twice. */
2582
2583 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2584 while (--i >= 0)
2585 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2586
2587 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2588 struct obj_symbol *sym;
2589 for (sym = f->symtab[i]; sym; sym = sym->next)
2590 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002591 && sym->secidx <= SHN_HIRESERVE
2592 && (sym->secidx >= SHN_LORESERVE
2593 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002594 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2595
2596 obj_symbol_patch(f, sec->idx, ofs, sym);
2597 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002598 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002599
2600 nsyms++;
2601 }
2602 }
2603
2604 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2605 }
2606
2607 return 1;
2608}
2609
2610
2611static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002612new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002613{
2614 struct new_module *module;
2615 struct obj_section *sec;
2616 void *image;
2617 int ret;
2618 tgt_long m_addr;
2619
2620 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002621 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002622 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002623 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002624 module = (struct new_module *) sec->contents;
2625 m_addr = sec->header.sh_addr;
2626
2627 module->size_of_struct = sizeof(*module);
2628 module->size = m_size;
2629 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2630
2631 sec = obj_find_section(f, "__ksymtab");
2632 if (sec && sec->header.sh_size) {
2633 module->syms = sec->header.sh_addr;
2634 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2635 }
2636
2637 if (n_ext_modules_used) {
2638 sec = obj_find_section(f, ".kmodtab");
2639 module->deps = sec->header.sh_addr;
2640 module->ndeps = n_ext_modules_used;
2641 }
2642
2643 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002644 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002645 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002646 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002647
2648 sec = obj_find_section(f, "__ex_table");
2649 if (sec) {
2650 module->ex_table_start = sec->header.sh_addr;
2651 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2652 }
2653
2654 sec = obj_find_section(f, ".text.init");
2655 if (sec) {
2656 module->runsize = sec->header.sh_addr - m_addr;
2657 }
2658 sec = obj_find_section(f, ".data.init");
2659 if (sec) {
2660 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002661 module->runsize > sec->header.sh_addr - m_addr)
2662 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002663 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002664 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2665 if (sec && sec->header.sh_size) {
2666 module->archdata_start = (void*)sec->header.sh_addr;
2667 module->archdata_end = module->archdata_start + sec->header.sh_size;
2668 }
2669 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2670 if (sec && sec->header.sh_size) {
2671 module->kallsyms_start = (void*)sec->header.sh_addr;
2672 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2673 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002674
Eric Andersen9f16d612000-06-12 23:11:16 +00002675 /* Whew! All of the initialization is complete. Collect the final
2676 module image and give it to the kernel. */
2677
2678 image = xmalloc(m_size);
2679 obj_create_image(f, image);
2680
Eric Andersencb3b9b12004-06-22 11:50:52 +00002681 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002682 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002683 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002684
2685 free(image);
2686
2687 return ret == 0;
2688}
2689
Eric Andersen9f16d612000-06-12 23:11:16 +00002690
2691/*======================================================================*/
2692
Eric Andersen044228d2001-07-17 01:12:36 +00002693static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002694obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2695 const char *string)
2696{
2697 struct obj_string_patch *p;
2698 struct obj_section *strsec;
2699 size_t len = strlen(string) + 1;
2700 char *loc;
2701
2702 p = xmalloc(sizeof(*p));
2703 p->next = f->string_patches;
2704 p->reloc_secidx = secidx;
2705 p->reloc_offset = offset;
2706 f->string_patches = p;
2707
2708 strsec = obj_find_section(f, ".kstrtab");
2709 if (strsec == NULL) {
2710 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2711 p->string_offset = 0;
2712 loc = strsec->contents;
2713 } else {
2714 p->string_offset = strsec->header.sh_size;
2715 loc = obj_extend_section(strsec, len);
2716 }
2717 memcpy(loc, string, len);
2718
2719 return 1;
2720}
2721
Eric Andersen044228d2001-07-17 01:12:36 +00002722static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002723obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2724 struct obj_symbol *sym)
2725{
2726 struct obj_symbol_patch *p;
2727
2728 p = xmalloc(sizeof(*p));
2729 p->next = f->symbol_patches;
2730 p->reloc_secidx = secidx;
2731 p->reloc_offset = offset;
2732 p->sym = sym;
2733 f->symbol_patches = p;
2734
2735 return 1;
2736}
2737
Eric Andersen044228d2001-07-17 01:12:36 +00002738static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002739{
2740 unsigned long i;
2741 int ret = 1;
2742
2743 for (i = 0; i < HASH_BUCKETS; ++i) {
2744 struct obj_symbol *sym;
2745 for (sym = f->symtab[i]; sym; sym = sym->next)
2746 if (sym->secidx == SHN_UNDEF) {
2747 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2748 sym->secidx = SHN_ABS;
2749 sym->value = 0;
2750 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002751 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002752 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00002753 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002754 ret = 0;
2755 }
2756 }
2757 }
2758
2759 return ret;
2760}
2761
Eric Andersen044228d2001-07-17 01:12:36 +00002762static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002763{
2764 struct common_entry {
2765 struct common_entry *next;
2766 struct obj_symbol *sym;
2767 } *common_head = NULL;
2768
2769 unsigned long i;
2770
2771 for (i = 0; i < HASH_BUCKETS; ++i) {
2772 struct obj_symbol *sym;
2773 for (sym = f->symtab[i]; sym; sym = sym->next)
2774 if (sym->secidx == SHN_COMMON) {
2775 /* Collect all COMMON symbols and sort them by size so as to
2776 minimize space wasted by alignment requirements. */
2777 {
2778 struct common_entry **p, *n;
2779 for (p = &common_head; *p; p = &(*p)->next)
2780 if (sym->size <= (*p)->sym->size)
2781 break;
2782
2783 n = alloca(sizeof(*n));
2784 n->next = *p;
2785 n->sym = sym;
2786 *p = n;
2787 }
2788 }
2789 }
2790
2791 for (i = 1; i < f->local_symtab_size; ++i) {
2792 struct obj_symbol *sym = f->local_symtab[i];
2793 if (sym && sym->secidx == SHN_COMMON) {
2794 struct common_entry **p, *n;
2795 for (p = &common_head; *p; p = &(*p)->next)
2796 if (sym == (*p)->sym)
2797 break;
2798 else if (sym->size < (*p)->sym->size) {
2799 n = alloca(sizeof(*n));
2800 n->next = *p;
2801 n->sym = sym;
2802 *p = n;
2803 break;
2804 }
2805 }
2806 }
2807
2808 if (common_head) {
2809 /* Find the bss section. */
2810 for (i = 0; i < f->header.e_shnum; ++i)
2811 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2812 break;
2813
2814 /* If for some reason there hadn't been one, create one. */
2815 if (i == f->header.e_shnum) {
2816 struct obj_section *sec;
2817
2818 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2819 f->sections[i] = sec = arch_new_section();
2820 f->header.e_shnum = i + 1;
2821
2822 memset(sec, 0, sizeof(*sec));
2823 sec->header.sh_type = SHT_PROGBITS;
2824 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2825 sec->name = ".bss";
2826 sec->idx = i;
2827 }
2828
2829 /* Allocate the COMMONS. */
2830 {
2831 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2832 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2833 struct common_entry *c;
2834
2835 for (c = common_head; c; c = c->next) {
2836 ElfW(Addr) align = c->sym->value;
2837
2838 if (align > max_align)
2839 max_align = align;
2840 if (bss_size & (align - 1))
2841 bss_size = (bss_size | (align - 1)) + 1;
2842
2843 c->sym->secidx = i;
2844 c->sym->value = bss_size;
2845
2846 bss_size += c->sym->size;
2847 }
2848
2849 f->sections[i]->header.sh_size = bss_size;
2850 f->sections[i]->header.sh_addralign = max_align;
2851 }
2852 }
2853
2854 /* For the sake of patch relocation and parameter initialization,
2855 allocate zeroed data for NOBITS sections now. Note that after
2856 this we cannot assume NOBITS are really empty. */
2857 for (i = 0; i < f->header.e_shnum; ++i) {
2858 struct obj_section *s = f->sections[i];
2859 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002860 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002861 s->contents = memset(xmalloc(s->header.sh_size),
2862 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002863 else
2864 s->contents = NULL;
2865
Eric Andersen9f16d612000-06-12 23:11:16 +00002866 s->header.sh_type = SHT_PROGBITS;
2867 }
2868 }
2869}
2870
Eric Andersen044228d2001-07-17 01:12:36 +00002871static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002872{
2873 unsigned long dot = 0;
2874 struct obj_section *sec;
2875
2876 /* Finalize the positions of the sections relative to one another. */
2877
2878 for (sec = f->load_order; sec; sec = sec->load_next) {
2879 ElfW(Addr) align;
2880
2881 align = sec->header.sh_addralign;
2882 if (align && (dot & (align - 1)))
2883 dot = (dot | (align - 1)) + 1;
2884
2885 sec->header.sh_addr = dot;
2886 dot += sec->header.sh_size;
2887 }
2888
2889 return dot;
2890}
2891
Eric Andersen044228d2001-07-17 01:12:36 +00002892static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002893{
2894 int i, n = f->header.e_shnum;
2895 int ret = 1;
2896
2897 /* Finalize the addresses of the sections. */
2898
2899 f->baseaddr = base;
2900 for (i = 0; i < n; ++i)
2901 f->sections[i]->header.sh_addr += base;
2902
2903 /* And iterate over all of the relocations. */
2904
2905 for (i = 0; i < n; ++i) {
2906 struct obj_section *relsec, *symsec, *targsec, *strsec;
2907 ElfW(RelM) * rel, *relend;
2908 ElfW(Sym) * symtab;
2909 const char *strtab;
2910
2911 relsec = f->sections[i];
2912 if (relsec->header.sh_type != SHT_RELM)
2913 continue;
2914
2915 symsec = f->sections[relsec->header.sh_link];
2916 targsec = f->sections[relsec->header.sh_info];
2917 strsec = f->sections[symsec->header.sh_link];
2918
2919 rel = (ElfW(RelM) *) relsec->contents;
2920 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2921 symtab = (ElfW(Sym) *) symsec->contents;
2922 strtab = (const char *) strsec->contents;
2923
2924 for (; rel < relend; ++rel) {
2925 ElfW(Addr) value = 0;
2926 struct obj_symbol *intsym = NULL;
2927 unsigned long symndx;
2928 ElfW(Sym) * extsym = 0;
2929 const char *errmsg;
2930
2931 /* Attempt to find a value to use for this relocation. */
2932
2933 symndx = ELFW(R_SYM) (rel->r_info);
2934 if (symndx) {
2935 /* Note we've already checked for undefined symbols. */
2936
2937 extsym = &symtab[symndx];
2938 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2939 /* Local symbols we look up in the local table to be sure
2940 we get the one that is really intended. */
2941 intsym = f->local_symtab[symndx];
2942 } else {
2943 /* Others we look up in the hash table. */
2944 const char *name;
2945 if (extsym->st_name)
2946 name = strtab + extsym->st_name;
2947 else
2948 name = f->sections[extsym->st_shndx]->name;
2949 intsym = obj_find_symbol(f, name);
2950 }
2951
2952 value = obj_symbol_final_value(f, intsym);
2953 intsym->referenced = 1;
2954 }
2955#if SHT_RELM == SHT_RELA
2956#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2957 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2958 if (!extsym || !extsym->st_name ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002959 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00002960#endif
2961 value += rel->r_addend;
2962#endif
2963
2964 /* Do it! */
2965 switch (arch_apply_relocation
2966 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002967 case obj_reloc_ok:
2968 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002969
Eric Andersen3b1a7442003-12-24 20:30:45 +00002970 case obj_reloc_overflow:
2971 errmsg = "Relocation overflow";
2972 goto bad_reloc;
2973 case obj_reloc_dangerous:
2974 errmsg = "Dangerous relocation";
2975 goto bad_reloc;
2976 case obj_reloc_unhandled:
2977 errmsg = "Unhandled relocation";
2978bad_reloc:
2979 if (extsym) {
2980 bb_error_msg("%s of type %ld for %s", errmsg,
2981 (long) ELFW(R_TYPE) (rel->r_info),
2982 strtab + extsym->st_name);
2983 } else {
2984 bb_error_msg("%s of type %ld", errmsg,
2985 (long) ELFW(R_TYPE) (rel->r_info));
2986 }
2987 ret = 0;
2988 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002989 }
2990 }
2991 }
2992
2993 /* Finally, take care of the patches. */
2994
2995 if (f->string_patches) {
2996 struct obj_string_patch *p;
2997 struct obj_section *strsec;
2998 ElfW(Addr) strsec_base;
2999 strsec = obj_find_section(f, ".kstrtab");
3000 strsec_base = strsec->header.sh_addr;
3001
3002 for (p = f->string_patches; p; p = p->next) {
3003 struct obj_section *targsec = f->sections[p->reloc_secidx];
3004 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3005 = strsec_base + p->string_offset;
3006 }
3007 }
3008
3009 if (f->symbol_patches) {
3010 struct obj_symbol_patch *p;
3011
3012 for (p = f->symbol_patches; p; p = p->next) {
3013 struct obj_section *targsec = f->sections[p->reloc_secidx];
3014 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3015 = obj_symbol_final_value(f, p->sym);
3016 }
3017 }
3018
3019 return ret;
3020}
3021
Eric Andersen044228d2001-07-17 01:12:36 +00003022static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003023{
3024 struct obj_section *sec;
3025 ElfW(Addr) base = f->baseaddr;
3026
3027 for (sec = f->load_order; sec; sec = sec->load_next) {
3028 char *secimg;
3029
Eric Andersen2bf658d2001-02-24 20:01:53 +00003030 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003031 continue;
3032
3033 secimg = image + (sec->header.sh_addr - base);
3034
3035 /* Note that we allocated data for NOBITS sections earlier. */
3036 memcpy(secimg, sec->contents, sec->header.sh_size);
3037 }
3038
3039 return 1;
3040}
3041
3042/*======================================================================*/
3043
Eric Andersen044228d2001-07-17 01:12:36 +00003044static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003045{
3046 struct obj_file *f;
3047 ElfW(Shdr) * section_headers;
3048 int shnum, i;
3049 char *shstrtab;
3050
3051 /* Read the file header. */
3052
3053 f = arch_new_file();
3054 memset(f, 0, sizeof(*f));
3055 f->symbol_cmp = strcmp;
3056 f->symbol_hash = obj_elf_hash;
3057 f->load_order_search_start = &f->load_order;
3058
3059 fseek(fp, 0, SEEK_SET);
3060 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003061 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003062 return NULL;
3063 }
3064
3065 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003066 || f->header.e_ident[EI_MAG1] != ELFMAG1
3067 || f->header.e_ident[EI_MAG2] != ELFMAG2
3068 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003069 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003070 return NULL;
3071 }
3072 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003073 || f->header.e_ident[EI_DATA] != ELFDATAM
3074 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3075 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003076 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003077 return NULL;
3078 }
3079 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003080 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003081 return NULL;
3082 }
3083
3084 /* Read the section headers. */
3085
3086 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003087 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003088 (unsigned long) f->header.e_shentsize,
3089 (unsigned long) sizeof(ElfW(Shdr)));
3090 return NULL;
3091 }
3092
3093 shnum = f->header.e_shnum;
3094 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3095 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3096
3097 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3098 fseek(fp, f->header.e_shoff, SEEK_SET);
3099 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003100 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003101 return NULL;
3102 }
3103
3104 /* Read the section data. */
3105
3106 for (i = 0; i < shnum; ++i) {
3107 struct obj_section *sec;
3108
3109 f->sections[i] = sec = arch_new_section();
3110 memset(sec, 0, sizeof(*sec));
3111
3112 sec->header = section_headers[i];
3113 sec->idx = i;
3114
Eric Andersen2bf658d2001-02-24 20:01:53 +00003115 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003116 case SHT_NULL:
3117 case SHT_NOTE:
3118 case SHT_NOBITS:
3119 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003120 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003121
3122 case SHT_PROGBITS:
3123#if LOADBITS
3124 if (!loadprogbits) {
3125 sec->contents = NULL;
3126 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003127 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003128#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003129 case SHT_SYMTAB:
3130 case SHT_STRTAB:
3131 case SHT_RELM:
3132 if (sec->header.sh_size > 0) {
3133 sec->contents = xmalloc(sec->header.sh_size);
3134 fseek(fp, sec->header.sh_offset, SEEK_SET);
3135 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3136 bb_perror_msg("error reading ELF section data");
3137 return NULL;
3138 }
3139 } else {
3140 sec->contents = NULL;
3141 }
3142 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003143
3144#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003145 case SHT_RELA:
3146 bb_error_msg("RELA relocations not supported on this architecture");
3147 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003148#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003149 case SHT_REL:
3150 bb_error_msg("REL relocations not supported on this architecture");
3151 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003152#endif
3153
Eric Andersen3b1a7442003-12-24 20:30:45 +00003154 default:
3155 if (sec->header.sh_type >= SHT_LOPROC) {
3156 /* Assume processor specific section types are debug
3157 info and can safely be ignored. If this is ever not
3158 the case (Hello MIPS?), don't put ifdefs here but
3159 create an arch_load_proc_section(). */
3160 break;
3161 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003162
Eric Andersen3b1a7442003-12-24 20:30:45 +00003163 bb_error_msg("can't handle sections of type %ld",
3164 (long) sec->header.sh_type);
3165 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003166 }
3167 }
3168
3169 /* Do what sort of interpretation as needed by each section. */
3170
3171 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3172
3173 for (i = 0; i < shnum; ++i) {
3174 struct obj_section *sec = f->sections[i];
3175 sec->name = shstrtab + sec->header.sh_name;
3176 }
3177
3178 for (i = 0; i < shnum; ++i) {
3179 struct obj_section *sec = f->sections[i];
3180
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003181 /* .modinfo should be contents only but gcc has no attribute for that.
3182 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3183 */
3184 if (strcmp(sec->name, ".modinfo") == 0)
3185 sec->header.sh_flags &= ~SHF_ALLOC;
3186
Eric Andersen9f16d612000-06-12 23:11:16 +00003187 if (sec->header.sh_flags & SHF_ALLOC)
3188 obj_insert_section_load_order(f, sec);
3189
3190 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003191 case SHT_SYMTAB:
3192 {
3193 unsigned long nsym, j;
3194 char *strtab;
3195 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003196
Eric Andersen3b1a7442003-12-24 20:30:45 +00003197 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3198 bb_error_msg("symbol size mismatch: %lu != %lu",
3199 (unsigned long) sec->header.sh_entsize,
3200 (unsigned long) sizeof(ElfW(Sym)));
3201 return NULL;
3202 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003203
Eric Andersen3b1a7442003-12-24 20:30:45 +00003204 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3205 strtab = f->sections[sec->header.sh_link]->contents;
3206 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003207
Eric Andersen3b1a7442003-12-24 20:30:45 +00003208 /* Allocate space for a table of local symbols. */
3209 j = f->local_symtab_size = sec->header.sh_info;
3210 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003211
Eric Andersen3b1a7442003-12-24 20:30:45 +00003212 /* Insert all symbols into the hash table. */
3213 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3214 ElfW(Addr) val = sym->st_value;
3215 const char *name;
3216 if (sym->st_name)
3217 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003218 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003219 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003220 else
3221 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003222
Eric Andersenbf833552003-08-13 19:56:33 +00003223#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003224 /*
3225 * For sh64 it is possible that the target of a branch
3226 * requires a mode switch (32 to 16 and back again).
3227 *
3228 * This is implied by the lsb being set in the target
3229 * address for SHmedia mode and clear for SHcompact.
3230 */
3231 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003232#endif
3233
Eric Andersen3b1a7442003-12-24 20:30:45 +00003234 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3235 val, sym->st_size);
3236 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003237 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003238 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003239
Eric Andersen3b1a7442003-12-24 20:30:45 +00003240 case SHT_RELM:
3241 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3242 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3243 (unsigned long) sec->header.sh_entsize,
3244 (unsigned long) sizeof(ElfW(RelM)));
3245 return NULL;
3246 }
3247 break;
3248 /* XXX Relocation code from modutils-2.3.19 is not here.
3249 * Why? That's about 20 lines of code from obj/obj_load.c,
3250 * which gets done in a second pass through the sections.
3251 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003252 }
3253 }
3254
3255 return f;
3256}
3257
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003258#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003259/*
3260 * load the unloaded sections directly into the memory allocated by
3261 * kernel for the module
3262 */
3263
Eric Andersenac5dbd12001-08-22 05:26:08 +00003264static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003265{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003266 ElfW(Addr) base = f->baseaddr;
3267 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003268
Eric Andersen8ae319a2001-05-21 16:09:18 +00003269 for (sec = f->load_order; sec; sec = sec->load_next) {
3270
3271 /* section already loaded? */
3272 if (sec->contents != NULL)
3273 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003274
Eric Andersen8ae319a2001-05-21 16:09:18 +00003275 if (sec->header.sh_size == 0)
3276 continue;
3277
3278 sec->contents = imagebase + (sec->header.sh_addr - base);
3279 fseek(fp, sec->header.sh_offset, SEEK_SET);
3280 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003281 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003282 return 0;
3283 }
3284
3285 }
3286 return 1;
3287}
3288#endif
3289
Eric Andersen9f16d612000-06-12 23:11:16 +00003290static void hide_special_symbols(struct obj_file *f)
3291{
3292 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003293 SPFX "cleanup_module",
3294 SPFX "init_module",
3295 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003296 NULL
3297 };
3298
3299 struct obj_symbol *sym;
3300 const char *const *p;
3301
3302 for (p = specials; *p; ++p)
3303 if ((sym = obj_find_symbol(f, *p)) != NULL)
3304 sym->info =
3305 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3306}
3307
Glenn L McGrath759515c2003-08-30 06:00:33 +00003308
Eric Andersen71ae64b2002-10-10 04:20:21 +00003309#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003310static int obj_gpl_license(struct obj_file *f, const char **license)
3311{
3312 struct obj_section *sec;
3313 /* This list must match *exactly* the list of allowable licenses in
3314 * linux/include/linux/module.h. Checking for leading "GPL" will not
3315 * work, somebody will use "GPL sucks, this is proprietary".
3316 */
3317 static const char *gpl_licenses[] = {
3318 "GPL",
3319 "GPL v2",
3320 "GPL and additional rights",
3321 "Dual BSD/GPL",
3322 "Dual MPL/GPL",
3323 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003324
Eric Andersen166fa462002-09-16 05:30:24 +00003325 if ((sec = obj_find_section(f, ".modinfo"))) {
3326 const char *value, *ptr, *endptr;
3327 ptr = sec->contents;
3328 endptr = ptr + sec->header.sh_size;
3329 while (ptr < endptr) {
3330 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3331 int i;
3332 if (license)
3333 *license = value+1;
3334 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3335 if (strcmp(value+1, gpl_licenses[i]) == 0)
3336 return(0);
3337 }
3338 return(2);
3339 }
3340 if (strchr(ptr, '\0'))
3341 ptr = strchr(ptr, '\0') + 1;
3342 else
3343 ptr = endptr;
3344 }
3345 }
3346 return(1);
3347}
3348
3349#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3350#define TAINT_PROPRIETORY_MODULE (1<<0)
3351#define TAINT_FORCED_MODULE (1<<1)
3352#define TAINT_UNSAFE_SMP (1<<2)
3353#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3354
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003355static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003356 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3357{
3358 char buf[80];
3359 int oldval;
3360 static int first = 1;
3361 if (fd < 0 && !kernel_has_tainted)
3362 return; /* New modutils on old kernel */
3363 printf("Warning: loading %s will taint the kernel: %s%s\n",
3364 m_name, text1, text2);
3365 if (first) {
3366 printf(" See %s for information about tainted modules\n", TAINT_URL);
3367 first = 0;
3368 }
3369 if (fd >= 0) {
3370 read(fd, buf, sizeof(buf)-1);
3371 buf[sizeof(buf)-1] = '\0';
3372 oldval = strtoul(buf, NULL, 10);
3373 sprintf(buf, "%d\n", oldval | taint);
3374 write(fd, buf, strlen(buf));
3375 }
3376}
3377
3378/* Check if loading this module will taint the kernel. */
3379static void check_tainted_module(struct obj_file *f, char *m_name)
3380{
3381 static const char tainted_file[] = TAINT_FILENAME;
3382 int fd, kernel_has_tainted;
3383 const char *ptr;
3384
3385 kernel_has_tainted = 1;
3386 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3387 if (errno == ENOENT)
3388 kernel_has_tainted = 0;
3389 else if (errno == EACCES)
3390 kernel_has_tainted = 1;
3391 else {
3392 perror(tainted_file);
3393 kernel_has_tainted = 0;
3394 }
3395 }
3396
3397 switch (obj_gpl_license(f, &ptr)) {
3398 case 0:
3399 break;
3400 case 1:
3401 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3402 break;
3403 case 2:
3404 /* The module has a non-GPL license so we pretend that the
3405 * kernel always has a taint flag to get a warning even on
3406 * kernels without the proc flag.
3407 */
3408 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3409 break;
3410 default:
3411 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3412 break;
3413 }
3414
3415 if (flag_force_load)
3416 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3417
3418 if (fd >= 0)
3419 close(fd);
3420}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003421#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3422#define check_tainted_module(x, y) do { } while(0);
3423#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003424
Eric Andersen889dd202003-01-23 04:48:34 +00003425#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3426/* add module source, timestamp, kernel version and a symbol for the
3427 * start of some sections. this info is used by ksymoops to do better
3428 * debugging.
3429 */
3430static int
3431get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3432{
3433#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003434 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003435#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003436 strncpy(str, "???", sizeof(str));
3437 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003438#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3439}
3440
3441/* add module source, timestamp, kernel version and a symbol for the
3442 * start of some sections. this info is used by ksymoops to do better
3443 * debugging.
3444 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003445static void
Eric Andersen889dd202003-01-23 04:48:34 +00003446add_ksymoops_symbols(struct obj_file *f, const char *filename,
3447 const char *m_name)
3448{
3449 static const char symprefix[] = "__insmod_";
3450 struct obj_section *sec;
3451 struct obj_symbol *sym;
3452 char *name, *absolute_filename;
3453 char str[STRVERSIONLEN], real[PATH_MAX];
3454 int i, l, lm_name, lfilename, use_ksymtab, version;
3455 struct stat statbuf;
3456
3457 static const char *section_names[] = {
3458 ".text",
3459 ".rodata",
3460 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003461 ".bss",
3462 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003463 };
3464
3465 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003466 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003467 }
3468 else {
3469 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003470 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003471 errno = save_errno;
3472 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003473 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003474 }
3475
3476 lm_name = strlen(m_name);
3477 lfilename = strlen(absolute_filename);
3478
3479 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3480 * are not to be exported. otherwise leave ksymtab alone for now, the
3481 * "export all symbols" compatibility code will export these symbols later.
3482 */
3483 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3484
3485 if ((sec = obj_find_section(f, ".this"))) {
3486 /* tag the module header with the object name, last modified
3487 * timestamp and module version. worst case for module version
3488 * is 0xffffff, decimal 16777215. putting all three fields in
3489 * one symbol is less readable but saves kernel space.
3490 */
3491 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003492 lm_name+ /* module name */
3493 2+ /* "_O" */
3494 lfilename+ /* object filename */
3495 2+ /* "_M" */
3496 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3497 2+ /* "_V" */
3498 8+ /* version in dec */
3499 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003500 name = xmalloc(l);
3501 if (stat(absolute_filename, &statbuf) != 0)
3502 statbuf.st_mtime = 0;
3503 version = get_module_version(f, str); /* -1 if not found */
3504 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003505 symprefix, m_name, absolute_filename,
3506 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3507 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003508 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003509 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3510 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003511 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003512 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003513 }
3514 free(absolute_filename);
3515#ifdef _NOT_SUPPORTED_
3516 /* record where the persistent data is going, same address as previous symbol */
3517
3518 if (f->persist) {
3519 l = sizeof(symprefix)+ /* "__insmod_" */
3520 lm_name+ /* module name */
3521 2+ /* "_P" */
3522 strlen(f->persist)+ /* data store */
3523 1; /* nul */
3524 name = xmalloc(l);
3525 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003526 symprefix, m_name, f->persist);
Eric Andersen889dd202003-01-23 04:48:34 +00003527 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003528 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003529 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003530 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003531 }
3532#endif /* _NOT_SUPPORTED_ */
3533 /* tag the desired sections if size is non-zero */
3534
3535 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3536 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003537 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003538 l = sizeof(symprefix)+ /* "__insmod_" */
3539 lm_name+ /* module name */
3540 2+ /* "_S" */
3541 strlen(sec->name)+ /* section name */
3542 2+ /* "_L" */
3543 8+ /* length in dec */
3544 1; /* nul */
3545 name = xmalloc(l);
3546 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003547 symprefix, m_name, sec->name,
3548 (long)sec->header.sh_size);
Eric Andersen889dd202003-01-23 04:48:34 +00003549 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003550 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003551 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003552 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003553 }
3554 }
3555}
3556#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3557
Eric Andersenbe65c352003-01-23 04:57:35 +00003558#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3559static void print_load_map(struct obj_file *f)
3560{
3561 struct obj_symbol *sym;
3562 struct obj_symbol **all, **p;
3563 struct obj_section *sec;
3564 int i, nsyms, *loaded;
3565
3566 /* Report on the section layout. */
3567
3568 printf("Sections: Size %-*s Align\n",
3569 (int) (2 * sizeof(void *)), "Address");
3570
3571 for (sec = f->load_order; sec; sec = sec->load_next) {
3572 int a;
3573 unsigned long tmp;
3574
3575 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3576 tmp >>= 1;
3577 if (a == -1)
3578 a = 0;
3579
3580 printf("%-15s %08lx %0*lx 2**%d\n",
3581 sec->name,
3582 (long)sec->header.sh_size,
3583 (int) (2 * sizeof(void *)),
3584 (long)sec->header.sh_addr,
3585 a);
3586 }
3587#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3588 /* Quick reference which section indicies are loaded. */
3589
3590 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3591 while (--i >= 0)
3592 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3593
3594 /* Collect the symbols we'll be listing. */
3595
3596 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3597 for (sym = f->symtab[i]; sym; sym = sym->next)
3598 if (sym->secidx <= SHN_HIRESERVE
3599 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3600 ++nsyms;
3601
3602 all = alloca(nsyms * sizeof(struct obj_symbol *));
3603
3604 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3605 for (sym = f->symtab[i]; sym; sym = sym->next)
3606 if (sym->secidx <= SHN_HIRESERVE
3607 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3608 *p++ = sym;
3609
3610 /* And list them. */
3611 printf("\nSymbols:\n");
3612 for (p = all; p < all + nsyms; ++p) {
3613 char type = '?';
3614 unsigned long value;
3615
3616 sym = *p;
3617 if (sym->secidx == SHN_ABS) {
3618 type = 'A';
3619 value = sym->value;
3620 } else if (sym->secidx == SHN_UNDEF) {
3621 type = 'U';
3622 value = 0;
3623 } else {
3624 sec = f->sections[sym->secidx];
3625
3626 if (sec->header.sh_type == SHT_NOBITS)
3627 type = 'B';
3628 else if (sec->header.sh_flags & SHF_ALLOC) {
3629 if (sec->header.sh_flags & SHF_EXECINSTR)
3630 type = 'T';
3631 else if (sec->header.sh_flags & SHF_WRITE)
3632 type = 'D';
3633 else
3634 type = 'R';
3635 }
3636 value = sym->value + sec->header.sh_addr;
3637 }
3638
3639 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
3640 type = tolower(type);
3641
3642 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3643 type, sym->name);
3644 }
3645#endif
3646}
3647
3648#endif
3649
Eric Andersen9f16d612000-06-12 23:11:16 +00003650extern int insmod_main( int argc, char **argv)
3651{
Eric Andersena18aaf12001-01-24 19:07:09 +00003652 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003653 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003654 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003655 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003656 unsigned long m_size;
3657 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003658 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003659 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003660 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003661 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003662 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003663#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003664 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003665 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003666 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003667#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003668#ifdef CONFIG_FEATURE_CLEAN_UP
3669 FILE *fp = 0;
3670#else
3671 FILE *fp;
3672#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003673#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3674 int flag_print_load_map = 0;
3675#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003676 int k_version = 0;
3677 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003678
Erik Andersene49d5ec2000-02-08 19:58:47 +00003679 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003680#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003681 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003682#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003683 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003684#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003685 {
3686 switch (opt) {
3687 case 'f': /* force loading */
3688 flag_force_load = 1;
3689 break;
3690 case 'k': /* module loaded by kerneld, auto-cleanable */
3691 flag_autoclean = 1;
3692 break;
3693 case 's': /* log to syslog */
3694 /* log to syslog -- not supported */
3695 /* but kernel needs this for request_module(), */
3696 /* as this calls: modprobe -k -s -- <module> */
3697 /* so silently ignore this flag */
3698 break;
3699 case 'v': /* verbose output */
3700 flag_verbose = 1;
3701 break;
3702 case 'q': /* silent */
3703 flag_quiet = 1;
3704 break;
3705 case 'x': /* do not export externs */
3706 flag_export = 0;
3707 break;
3708 case 'o': /* name the output module */
3709 free(m_name);
3710 m_name = bb_xstrdup(optarg);
3711 break;
3712 case 'L': /* Stub warning */
3713 /* This is needed for compatibility with modprobe.
3714 * In theory, this does locking, but we don't do
3715 * that. So be careful and plan your life around not
3716 * loading the same module 50 times concurrently. */
3717 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003718#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003719 case 'm': /* print module load map */
3720 flag_print_load_map = 1;
3721 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003722#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003723 default:
3724 bb_show_usage();
3725 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003726 }
Eric Andersen03d80912003-12-19 21:04:19 +00003727
Eric Andersena18aaf12001-01-24 19:07:09 +00003728 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003729 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003730 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003731
Erik Andersene49d5ec2000-02-08 19:58:47 +00003732 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003733 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003734 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003735 len = strlen(tmp);
3736
Eric Andersen03d80912003-12-19 21:04:19 +00003737 if (uname(&myuname) == 0) {
3738 if (myuname.release[0] == '2') {
3739 k_version = myuname.release[2] - '0';
3740 }
3741 }
3742
3743#if defined(CONFIG_FEATURE_2_6_MODULES)
3744 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003745 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003746 len-=3;
3747 tmp[len] = '\0';
3748 }
3749 else
3750#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003751 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3752 len-=2;
3753 tmp[len] = '\0';
3754 }
Eric Andersen2d342152002-06-18 05:16:25 +00003755
Eric Andersen03d80912003-12-19 21:04:19 +00003756
3757#if defined(CONFIG_FEATURE_2_6_MODULES)
3758 if (k_version > 4)
3759 bb_xasprintf(&m_fullName, "%s.ko", tmp);
3760 else
Eric Andersen03d80912003-12-19 21:04:19 +00003761#endif
Eric Andersen66e21fd2004-01-05 23:49:37 +00003762 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003763
Eric Andersen61f83052002-06-22 17:15:42 +00003764 if (!m_name) {
3765 m_name = tmp;
3766 } else {
3767 free(tmp1);
3768 tmp1 = 0; /* flag for free(m_name) before exit() */
3769 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003770
Eric Andersen14d35432001-05-14 17:07:32 +00003771 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003772 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3773 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003774 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3775 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003776 if (k_version) { /* uname succeedd */
3777 char *module_dir;
3778 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003779 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003780
Eric Andersen03d80912003-12-19 21:04:19 +00003781 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003782 /* Jump through hoops in case /lib/modules/`uname -r`
3783 * is a symlink. We do not want recursive_action to
3784 * follow symlinks, but we do want to follow the
3785 * /lib/modules/`uname -r` dir, So resolve it ourselves
3786 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00003787 if (realpath (tmdn, real_module_dir) == NULL)
3788 module_dir = tmdn;
3789 else
3790 module_dir = real_module_dir;
3791 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003792 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00003793 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00003794 }
3795
3796 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00003797 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003798 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003799 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003800
Eric Andersen03d80912003-12-19 21:04:19 +00003801 free(m_filename);
3802 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003803 if (realpath (_PATH_MODULES, module_dir) == NULL)
3804 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003805 /* No module found under /lib/modules/`uname -r`, this
3806 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00003807 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00003808 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00003809 {
Eric Andersen61f83052002-06-22 17:15:42 +00003810 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00003811 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00003812 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003813 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00003814 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00003815 }
3816 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003817 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00003818 }
Eric Andersen03d80912003-12-19 21:04:19 +00003819 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003820 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00003821
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00003822 if (!flag_quiet)
3823 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003824
Eric Andersene7047882003-12-11 01:42:13 +00003825#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003826 if (k_version > 4)
3827 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003828 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00003829 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003830 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00003831 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003832#endif
3833
Eric Andersen8ae319a2001-05-21 16:09:18 +00003834 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003835 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003836
Eric Andersen9f16d612000-06-12 23:11:16 +00003837 if (get_modinfo_value(f, "kernel_version") == NULL)
3838 m_has_modinfo = 0;
3839 else
3840 m_has_modinfo = 1;
3841
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003842#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003843 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00003844 if (!flag_quiet) {
3845 if (uname(&uts_info) < 0)
3846 uts_info.release[0] = '\0';
3847 if (m_has_modinfo) {
3848 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00003849 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003850 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00003851 "compiled for");
3852 goto out;
3853 }
3854 }
3855
3856 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
3857 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003858 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003859 "\t%s was compiled for kernel version %s\n"
3860 "\twhile this kernel is version %s",
3861 m_filename, m_strversion, uts_info.release);
3862 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003863 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003864 "\t%s was compiled for kernel version %s\n"
3865 "\twhile this kernel is version %s.",
3866 m_filename, m_strversion, uts_info.release);
3867 goto out;
3868 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003869 }
3870 }
3871 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003872#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003873
Eric Andersencb3b9b12004-06-22 11:50:52 +00003874 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003875 if (!new_get_kernel_symbols())
3876 goto out;
3877 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00003878 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003879 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003880 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00003881 }
3882
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003883#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003884 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00003885 if (m_has_modinfo)
3886 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003887
3888 if (m_crcs != k_crcs)
3889 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003890#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003891
Erik Andersene49d5ec2000-02-08 19:58:47 +00003892 /* Let the module know about the kernel symbols. */
3893 add_kernel_symbols(f);
3894
Eric Andersen9f16d612000-06-12 23:11:16 +00003895 /* Allocate common symbols, symbol tables, and string tables. */
3896
Eric Andersencb3b9b12004-06-22 11:50:52 +00003897 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003898 {
3899 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003900 }
3901
Eric Andersen9f16d612000-06-12 23:11:16 +00003902 if (!obj_check_undefineds(f)) {
3903 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003904 }
3905 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00003906 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003907
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003908 /* done with the module name, on to the optional var=value arguments */
3909 ++optind;
3910
Eric Andersen9f16d612000-06-12 23:11:16 +00003911 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00003912 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00003913 {
3914 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003915 }
3916 }
3917
Eric Andersen9f16d612000-06-12 23:11:16 +00003918 arch_create_got(f);
3919 hide_special_symbols(f);
3920
Eric Andersen889dd202003-01-23 04:48:34 +00003921#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3922 add_ksymoops_symbols(f, m_filename, m_name);
3923#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3924
Eric Andersencb3b9b12004-06-22 11:50:52 +00003925 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003926
Erik Andersene49d5ec2000-02-08 19:58:47 +00003927 /* Find current size of the module */
3928 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003929
3930
Erik Andersene49d5ec2000-02-08 19:58:47 +00003931 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00003932 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003933 case EEXIST:
3934 bb_error_msg("A module named %s already exists", m_name);
3935 goto out;
3936 case ENOMEM:
3937 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
3938 m_size);
3939 goto out;
3940 default:
3941 bb_perror_msg("create_module: %s", m_name);
3942 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003943 }
Erik Andersend387d011999-12-21 02:55:11 +00003944
Eric Andersen8ae319a2001-05-21 16:09:18 +00003945#if !LOADBITS
3946 /*
3947 * the PROGBITS section was not loaded by the obj_load
3948 * now we can load them directly into the kernel memory
3949 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00003950 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00003951 delete_module(m_name);
3952 goto out;
3953 }
Eric Andersen03d80912003-12-19 21:04:19 +00003954#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00003955
Eric Andersen9f16d612000-06-12 23:11:16 +00003956 if (!obj_relocate(f, m_addr)) {
3957 delete_module(m_name);
3958 goto out;
3959 }
Erik Andersend387d011999-12-21 02:55:11 +00003960
Eric Andersencb3b9b12004-06-22 11:50:52 +00003961 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00003962 {
3963 delete_module(m_name);
3964 goto out;
3965 }
3966
Eric Andersenbe65c352003-01-23 04:57:35 +00003967#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3968 if(flag_print_load_map)
3969 print_load_map(f);
3970#endif
3971
Matt Kraai3e856ce2000-12-01 02:55:13 +00003972 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003973
3974out:
Eric Andersen61f83052002-06-22 17:15:42 +00003975#ifdef CONFIG_FEATURE_CLEAN_UP
3976 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003977 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00003978 if(tmp1) {
3979 free(tmp1);
3980 } else {
3981 free(m_name);
3982 }
3983 free(m_filename);
3984#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00003985 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003986}
Eric Andersene7047882003-12-11 01:42:13 +00003987
3988
3989#endif
3990
3991
3992#ifdef CONFIG_FEATURE_2_6_MODULES
3993
3994#include <sys/mman.h>
3995#include <asm/unistd.h>
3996#include <sys/syscall.h>
3997
3998/* We use error numbers in a loose translation... */
3999static const char *moderror(int err)
4000{
4001 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004002 case ENOEXEC:
4003 return "Invalid module format";
4004 case ENOENT:
4005 return "Unknown symbol in module";
4006 case ESRCH:
4007 return "Module has wrong symbol version";
4008 case EINVAL:
4009 return "Invalid parameters";
4010 default:
4011 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004012 }
4013}
4014
4015extern int insmod_ng_main( int argc, char **argv)
4016{
4017 int i;
4018 int fd;
4019 long int ret;
4020 struct stat st;
4021 unsigned long len;
4022 void *map;
4023 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004024
Eric Andersene7047882003-12-11 01:42:13 +00004025 filename = argv[1];
4026 if (!filename) {
4027 bb_show_usage();
4028 return -1;
4029 }
4030
4031 /* Rest is options */
4032 for (i = 2; i < argc; i++) {
4033 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4034 /* Spaces handled by "" pairs, but no way of escaping quotes */
4035 if (strchr(argv[i], ' ')) {
4036 strcat(options, "\"");
4037 strcat(options, argv[i]);
4038 strcat(options, "\"");
4039 } else {
4040 strcat(options, argv[i]);
4041 }
4042 strcat(options, " ");
4043 }
4044
4045 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4046 bb_perror_msg_and_die("cannot open module `%s'", filename);
4047 }
4048
4049 fstat(fd, &st);
4050 len = st.st_size;
4051 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4052 if (map == MAP_FAILED) {
4053 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4054 }
4055
4056 ret = syscall(__NR_init_module, map, len, options);
4057 if (ret != 0) {
4058 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004059 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004060 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004061
Eric Andersene7047882003-12-11 01:42:13 +00004062 return 0;
4063}
4064
4065#endif