blob: c057774b6ad47810c2f43b3ea200004c71d0e6d5 [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 Andersena4d27d22004-08-19 19:17:30 +00005 * This version of insmod supports x86, x86_64, ARM, SH3/4/5, powerpc, m68k,
Eric Andersenee70fa52004-05-26 11:38:46 +00006 * MIPS, v850e, and H8/300.
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
112#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000113#define CONFIG_USE_PLT_ENTRIES
114#define CONFIG_PLT_ENTRY_SIZE 8
115#define CONFIG_USE_GOT_ENTRIES
116#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000117#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000118
Eric Andersencffd5022002-05-24 06:50:15 +0000119#define MATCH_MACHINE(x) (x == EM_ARM)
120#define SHT_RELM SHT_REL
121#define Elf32_RelM Elf32_Rel
122#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000123#endif
124
Eric Andersenbf77f612003-01-23 06:02:39 +0000125#if defined(__s390__)
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 Andersenbf77f612003-01-23 06:02:39 +0000131
132#define MATCH_MACHINE(x) (x == EM_S390)
133#define SHT_RELM SHT_RELA
134#define Elf32_RelM Elf32_Rela
135#define ELFCLASSM ELFCLASS32
136#endif
137
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000138#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000139#define CONFIG_USE_GOT_ENTRIES
140#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000141#define CONFIG_USE_SINGLE
142
143#ifndef EM_486
144#define MATCH_MACHINE(x) (x == EM_386)
145#else
146#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
147#endif
148
149#define SHT_RELM SHT_REL
150#define Elf32_RelM Elf32_Rel
151#define ELFCLASSM ELFCLASS32
152#endif
153
Eric Andersena4d27d22004-08-19 19:17:30 +0000154#if defined(__x86_64__)
155#define MATCH_MACHINE(x) (x == EM_X86_64)
156#define SHT_RELM SHT_REL
157#define Elf64_RelM Elf64_Rel
158#define ELFCLASSM ELFCLASS64
159#endif
160
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000161#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000162#define CONFIG_USE_GOT_ENTRIES
163#define CONFIG_GOT_ENTRY_SIZE 4
164#define CONFIG_USE_SINGLE
165
166#define MATCH_MACHINE(x) (x == EM_68K)
167#define SHT_RELM SHT_RELA
168#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000169#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000170#endif
171
Eric Andersen2bf658d2001-02-24 20:01:53 +0000172#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000173/* Account for ELF spec changes. */
174#ifndef EM_MIPS_RS3_LE
175#ifdef EM_MIPS_RS4_BE
176#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
177#else
178#define EM_MIPS_RS3_LE 10
179#endif
180#endif /* !EM_MIPS_RS3_LE */
181
182#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
183#define SHT_RELM SHT_REL
184#define Elf32_RelM Elf32_Rel
185#define ELFCLASSM ELFCLASS32
186#define ARCHDATAM "__dbe_table"
187#endif
188
189#if defined(__powerpc__)
190#define CONFIG_USE_PLT_ENTRIES
191#define CONFIG_PLT_ENTRY_SIZE 16
192#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000193#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000194#define CONFIG_USE_LIST
195
196#define MATCH_MACHINE(x) (x == EM_PPC)
197#define SHT_RELM SHT_RELA
198#define Elf32_RelM Elf32_Rela
199#define ELFCLASSM ELFCLASS32
200#define ARCHDATAM "__ftr_fixup"
201#endif
202
203#if defined(__sh__)
204#define CONFIG_USE_GOT_ENTRIES
205#define CONFIG_GOT_ENTRY_SIZE 4
206#define CONFIG_USE_SINGLE
207
208#define MATCH_MACHINE(x) (x == EM_SH)
209#define SHT_RELM SHT_RELA
210#define Elf32_RelM Elf32_Rela
211#define ELFCLASSM ELFCLASS32
212
Eric Andersenbf833552003-08-13 19:56:33 +0000213/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000214/* I'm not sure about big endian, so let's warn: */
215
Eric Andersenbf833552003-08-13 19:56:33 +0000216#if defined(__sh__) && defined(__BIG_ENDIAN__)
217#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000218#endif
219
220/* it may or may not work on the SH1/SH2... So let's error on those
221 also */
Eric Andersenbf833552003-08-13 19:56:33 +0000222#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && \
223 (defined(__sh__))
224#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000225#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000226#endif
227
Miles Baderae28b042002-04-01 09:34:25 +0000228#if defined (__v850e__)
229#define CONFIG_USE_PLT_ENTRIES
230#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000231#define CONFIG_USE_SINGLE
232
233#ifndef EM_CYGNUS_V850 /* grumble */
234#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000235#endif
236
Eric Andersencffd5022002-05-24 06:50:15 +0000237#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
238#define SHT_RELM SHT_RELA
239#define Elf32_RelM Elf32_Rela
240#define ELFCLASSM ELFCLASS32
241
242#define SYMBOL_PREFIX "_"
243#endif
244
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +0000245#if defined(__cris__)
246#ifndef EM_CRIS
247#define EM_CRIS 76
248#define R_CRIS_NONE 0
249#define R_CRIS_32 3
250#endif
251
252#define MATCH_MACHINE(x) (x == EM_CRIS)
253#define SHT_RELM SHT_RELA
254#define Elf32_RelM Elf32_Rela
255#define ELFCLASSM ELFCLASS32
256#endif
257
Eric Andersenee70fa52004-05-26 11:38:46 +0000258#if defined(__H8300H__) || defined(__H8300S__)
259#define CONFIG_USE_SINGLE
260
261#define MATCH_MACHINE(x) (x == EM_H8_300)
262#define SHT_RELM SHT_RELA
263#define Elf32_RelM Elf32_Rela
264
265#define ELFCLASSM ELFCLASS32
266#define SYMBOL_PREFIX "_"
267#endif
268
Eric Andersencffd5022002-05-24 06:50:15 +0000269#ifndef SHT_RELM
270#error Sorry, but insmod.c does not yet support this architecture...
271#endif
272
273
Eric Andersen9f16d612000-06-12 23:11:16 +0000274//----------------------------------------------------------------------------
275//--------modutils module.h, lines 45-242
276//----------------------------------------------------------------------------
277
278/* Definitions for the Linux module syscall interface.
279 Copyright 1996, 1997 Linux International.
280
281 Contributed by Richard Henderson <rth@tamu.edu>
282
283 This file is part of the Linux modutils.
284
285 This program is free software; you can redistribute it and/or modify it
286 under the terms of the GNU General Public License as published by the
287 Free Software Foundation; either version 2 of the License, or (at your
288 option) any later version.
289
290 This program is distributed in the hope that it will be useful, but
291 WITHOUT ANY WARRANTY; without even the implied warranty of
292 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
293 General Public License for more details.
294
295 You should have received a copy of the GNU General Public License
296 along with this program; if not, write to the Free Software Foundation,
297 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
298
299
300#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000301static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000302
Eric Andersena4d27d22004-08-19 19:17:30 +0000303#ident "$Id: insmod.c,v 1.123 2004/08/19 19:17:30 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000304
305/*======================================================================*/
306/* For sizeof() which are related to the module platform and not to the
307 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
308
309#define tgt_sizeof_char sizeof(char)
310#define tgt_sizeof_short sizeof(short)
311#define tgt_sizeof_int sizeof(int)
312#define tgt_sizeof_long sizeof(long)
313#define tgt_sizeof_char_p sizeof(char *)
314#define tgt_sizeof_void_p sizeof(void *)
315#define tgt_long long
316
317#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
318#undef tgt_sizeof_long
319#undef tgt_sizeof_char_p
320#undef tgt_sizeof_void_p
321#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000322static const int tgt_sizeof_long = 8;
323static const int tgt_sizeof_char_p = 8;
324static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000325#define tgt_long long long
326#endif
327
328/*======================================================================*/
329/* The structures used in Linux 2.1. */
330
331/* Note: new_module_symbol does not use tgt_long intentionally */
332struct new_module_symbol
333{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000334 unsigned long value;
335 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000336};
337
338struct new_module_persist;
339
340struct new_module_ref
341{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000342 unsigned tgt_long dep; /* kernel addresses */
343 unsigned tgt_long ref;
344 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000345};
346
347struct new_module
348{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000349 unsigned tgt_long size_of_struct; /* == sizeof(module) */
350 unsigned tgt_long next;
351 unsigned tgt_long name;
352 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000353
Eric Andersen3b1a7442003-12-24 20:30:45 +0000354 tgt_long usecount;
355 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000356
Eric Andersen3b1a7442003-12-24 20:30:45 +0000357 unsigned nsyms;
358 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000359
Eric Andersen3b1a7442003-12-24 20:30:45 +0000360 unsigned tgt_long syms;
361 unsigned tgt_long deps;
362 unsigned tgt_long refs;
363 unsigned tgt_long init;
364 unsigned tgt_long cleanup;
365 unsigned tgt_long ex_table_start;
366 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000367#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000368 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000369#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000370 /* Everything after here is extension. */
371 unsigned tgt_long persist_start;
372 unsigned tgt_long persist_end;
373 unsigned tgt_long can_unload;
374 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000375 const char *kallsyms_start; /* All symbols for kernel debugging */
376 const char *kallsyms_end;
377 const char *archdata_start; /* arch specific data for module */
378 const char *archdata_end;
379 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000380};
381
Eric Andersencffd5022002-05-24 06:50:15 +0000382#ifdef ARCHDATAM
383#define ARCHDATA_SEC_NAME ARCHDATAM
384#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000385#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000386#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000387#define KALLSYMS_SEC_NAME "__kallsyms"
388
389
Eric Andersen9f16d612000-06-12 23:11:16 +0000390struct new_module_info
391{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned long addr;
393 unsigned long size;
394 unsigned long flags;
395 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000396};
397
398/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000399static const int NEW_MOD_RUNNING = 1;
400static const int NEW_MOD_DELETED = 2;
401static const int NEW_MOD_AUTOCLEAN = 4;
402static const int NEW_MOD_VISITED = 8;
403static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404
Eric Andersencb3b9b12004-06-22 11:50:52 +0000405int init_module(const char *name, const struct new_module *);
406int query_module(const char *name, int which, void *buf,
407 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000408
409/* Values for query_module's which. */
410
Mark Whitley59ab0252001-01-23 22:30:04 +0000411static const int QM_MODULES = 1;
412static const int QM_DEPS = 2;
413static const int QM_REFS = 3;
414static const int QM_SYMBOLS = 4;
415static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000416
417/*======================================================================*/
418/* The system calls unchanged between 2.0 and 2.1. */
419
420unsigned long create_module(const char *, size_t);
421int delete_module(const char *);
422
423
424#endif /* module.h */
425
426//----------------------------------------------------------------------------
427//--------end of modutils module.h
428//----------------------------------------------------------------------------
429
430
431
432//----------------------------------------------------------------------------
433//--------modutils obj.h, lines 253-462
434//----------------------------------------------------------------------------
435
436/* Elf object file loading and relocation routines.
437 Copyright 1996, 1997 Linux International.
438
439 Contributed by Richard Henderson <rth@tamu.edu>
440
441 This file is part of the Linux modutils.
442
443 This program is free software; you can redistribute it and/or modify it
444 under the terms of the GNU General Public License as published by the
445 Free Software Foundation; either version 2 of the License, or (at your
446 option) any later version.
447
448 This program is distributed in the hope that it will be useful, but
449 WITHOUT ANY WARRANTY; without even the implied warranty of
450 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
451 General Public License for more details.
452
453 You should have received a copy of the GNU General Public License
454 along with this program; if not, write to the Free Software Foundation,
455 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
456
457
458#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000459static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000460
Eric Andersena4d27d22004-08-19 19:17:30 +0000461#ident "$Id: insmod.c,v 1.123 2004/08/19 19:17:30 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000462
463/* The relocatable object is manipulated using elfin types. */
464
465#include <stdio.h>
466#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000467#include <endian.h>
468
469#if __BYTE_ORDER == __LITTLE_ENDIAN
470#define ELFDATAM ELFDATA2LSB
471#elif __BYTE_ORDER == __BIG_ENDIAN
472#define ELFDATAM ELFDATA2MSB
473#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000474
Eric Andersen9f16d612000-06-12 23:11:16 +0000475#ifndef ElfW
476# if ELFCLASSM == ELFCLASS32
477# define ElfW(x) Elf32_ ## x
478# define ELFW(x) ELF32_ ## x
479# else
480# define ElfW(x) Elf64_ ## x
481# define ELFW(x) ELF64_ ## x
482# endif
483#endif
484
Eric Andersen85e5e722003-07-22 08:56:55 +0000485/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000486#ifndef ELF32_ST_INFO
487# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
488#endif
489
490#ifndef ELF64_ST_INFO
491# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
492#endif
493
494struct obj_string_patch;
495struct obj_symbol_patch;
496
497struct obj_section
498{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000499 ElfW(Shdr) header;
500 const char *name;
501 char *contents;
502 struct obj_section *load_next;
503 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000504};
505
506struct obj_symbol
507{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000508 struct obj_symbol *next; /* hash table link */
509 const char *name;
510 unsigned long value;
511 unsigned long size;
512 int secidx; /* the defining section index/module */
513 int info;
514 int ksymidx; /* for export to the kernel symtab */
515 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000516};
517
518/* Hardcode the hash table size. We shouldn't be needing so many
519 symbols that we begin to degrade performance, and we get a big win
520 by giving the compiler a constant divisor. */
521
522#define HASH_BUCKETS 521
523
524struct obj_file
525{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000526 ElfW(Ehdr) header;
527 ElfW(Addr) baseaddr;
528 struct obj_section **sections;
529 struct obj_section *load_order;
530 struct obj_section **load_order_search_start;
531 struct obj_string_patch *string_patches;
532 struct obj_symbol_patch *symbol_patches;
533 int (*symbol_cmp)(const char *, const char *);
534 unsigned long (*symbol_hash)(const char *);
535 unsigned long local_symtab_size;
536 struct obj_symbol **local_symtab;
537 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000538};
539
540enum obj_reloc
541{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000542 obj_reloc_ok,
543 obj_reloc_overflow,
544 obj_reloc_dangerous,
545 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000546};
547
548struct obj_string_patch
549{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000550 struct obj_string_patch *next;
551 int reloc_secidx;
552 ElfW(Addr) reloc_offset;
553 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000554};
555
556struct obj_symbol_patch
557{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000558 struct obj_symbol_patch *next;
559 int reloc_secidx;
560 ElfW(Addr) reloc_offset;
561 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000562};
563
564
565/* Generic object manipulation routines. */
566
Eric Andersen044228d2001-07-17 01:12:36 +0000567static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000568
Eric Andersen044228d2001-07-17 01:12:36 +0000569static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000570
Eric Andersen044228d2001-07-17 01:12:36 +0000571static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000572 const char *name);
573
Eric Andersen044228d2001-07-17 01:12:36 +0000574static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000575 struct obj_symbol *sym);
576
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000577#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000578static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000579 int (*cmp)(const char *, const char *),
580 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000581#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000584 const char *name);
585
Eric Andersen044228d2001-07-17 01:12:36 +0000586static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000587 struct obj_section *sec);
588
Eric Andersen044228d2001-07-17 01:12:36 +0000589static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000590 const char *name,
591 unsigned long align,
592 unsigned long size);
593
Eric Andersen044228d2001-07-17 01:12:36 +0000594static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000595 const char *name,
596 unsigned long align,
597 unsigned long size);
598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000602 const char *string);
603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000605 struct obj_symbol *sym);
606
Eric Andersen044228d2001-07-17 01:12:36 +0000607static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000612
Eric Andersen044228d2001-07-17 01:12:36 +0000613static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000614
Eric Andersen044228d2001-07-17 01:12:36 +0000615static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000618
619/* Architecture specific manipulation routines. */
620
Eric Andersen044228d2001-07-17 01:12:36 +0000621static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000628 struct obj_section *targsec,
629 struct obj_section *symsec,
630 struct obj_symbol *sym,
631 ElfW(RelM) *rel, ElfW(Addr) value);
632
Eric Andersencffd5022002-05-24 06:50:15 +0000633static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000634
Glenn L McGrath759515c2003-08-30 06:00:33 +0000635static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000636
Eric Andersen9f16d612000-06-12 23:11:16 +0000637#endif /* obj.h */
638//----------------------------------------------------------------------------
639//--------end of modutils obj.h
640//----------------------------------------------------------------------------
641
642
Miles Baderae28b042002-04-01 09:34:25 +0000643/* SPFX is always a string, so it can be concatenated to string constants. */
644#ifdef SYMBOL_PREFIX
645#define SPFX SYMBOL_PREFIX
646#else
647#define SPFX ""
648#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000649
Erik Andersen02104321999-12-17 18:57:34 +0000650
Erik Andersend387d011999-12-21 02:55:11 +0000651#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000652static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000653
Eric Andersen9f16d612000-06-12 23:11:16 +0000654/*======================================================================*/
655
Eric Andersen044228d2001-07-17 01:12:36 +0000656static int flag_force_load = 0;
657static int flag_autoclean = 0;
658static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000659static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000660static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
662
663/*======================================================================*/
664
Eric Andersencffd5022002-05-24 06:50:15 +0000665#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000666
Eric Andersencffd5022002-05-24 06:50:15 +0000667struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000668{
Eric Andersencffd5022002-05-24 06:50:15 +0000669 struct arch_list_entry *next;
670 CONFIG_LIST_ARCHTYPE addend;
671 int offset;
672 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000673};
Eric Andersencffd5022002-05-24 06:50:15 +0000674
Eric Andersen21adca72000-12-06 18:18:26 +0000675#endif
676
Eric Andersencffd5022002-05-24 06:50:15 +0000677#if defined(CONFIG_USE_SINGLE)
678
679struct arch_single_entry
680{
Eric Andersen9f16d612000-06-12 23:11:16 +0000681 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000682 int inited : 1;
683 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000684};
Eric Andersencffd5022002-05-24 06:50:15 +0000685
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000686#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000687
Eric Andersen2bf658d2001-02-24 20:01:53 +0000688#if defined(__mips__)
689struct mips_hi16
690{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000691 struct mips_hi16 *next;
692 Elf32_Addr *addr;
693 Elf32_Addr value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000694};
695#endif
696
Eric Andersenfe4208f2000-09-24 03:44:29 +0000697struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000698 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000699#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000700 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000701#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000702#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000703 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000704#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000705#if defined(__mips__)
706 struct mips_hi16 *mips_hi16_list;
707#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000708};
709
Eric Andersenfe4208f2000-09-24 03:44:29 +0000710struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000711 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000712#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000713#if defined(CONFIG_USE_PLT_LIST)
714 struct arch_list_entry *pltent;
715#else
716 struct arch_single_entry pltent;
717#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000718#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000719#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000720 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000721#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000722};
723
724
Eric Andersen9f16d612000-06-12 23:11:16 +0000725struct external_module {
726 const char *name;
727 ElfW(Addr) addr;
728 int used;
729 size_t nsyms;
730 struct new_module_symbol *syms;
731};
732
Eric Andersen044228d2001-07-17 01:12:36 +0000733static struct new_module_symbol *ksyms;
734static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000735
Eric Andersen044228d2001-07-17 01:12:36 +0000736static struct external_module *ext_modules;
737static int n_ext_modules;
738static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000739extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000740
Eric Andersen61f83052002-06-22 17:15:42 +0000741static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000742static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000743
Eric Andersenfe4208f2000-09-24 03:44:29 +0000744
Erik Andersen02104321999-12-17 18:57:34 +0000745
Eric Andersen9f16d612000-06-12 23:11:16 +0000746/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000747
Eric Andersen9f16d612000-06-12 23:11:16 +0000748
Eric Andersen14d35432001-05-14 17:07:32 +0000749static int check_module_name_match(const char *filename, struct stat *statbuf,
750 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000751{
Eric Andersen14d35432001-05-14 17:07:32 +0000752 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000753
Eric Andersen14d35432001-05-14 17:07:32 +0000754 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000755 return (FALSE);
756 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000757 char *tmp, *tmp1 = bb_xstrdup(filename);
758 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000759 if (strcmp(tmp, fullname) == 0) {
760 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000761 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000762 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000763 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000764 }
Eric Andersen14d35432001-05-14 17:07:32 +0000765 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000766 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000767 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000768}
769
Erik Andersen02104321999-12-17 18:57:34 +0000770
Eric Andersen9f16d612000-06-12 23:11:16 +0000771/*======================================================================*/
772
Eric Andersen044228d2001-07-17 01:12:36 +0000773static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000774{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000776 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000777
Eric Andersencffd5022002-05-24 06:50:15 +0000778 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000779
Eric Andersen9f16d612000-06-12 23:11:16 +0000780 return &f->root;
781}
782
Eric Andersen044228d2001-07-17 01:12:36 +0000783static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000784{
785 return xmalloc(sizeof(struct obj_section));
786}
787
Eric Andersen044228d2001-07-17 01:12:36 +0000788static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000789{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000791 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000792
Eric Andersencffd5022002-05-24 06:50:15 +0000793 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000794
Eric Andersen9f16d612000-06-12 23:11:16 +0000795 return &sym->root;
796}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000797
Eric Andersen044228d2001-07-17 01:12:36 +0000798static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000799arch_apply_relocation(struct obj_file *f,
800 struct obj_section *targsec,
801 struct obj_section *symsec,
802 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000803 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000804{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000805 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000806 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000807 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
808 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000809#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
810 struct arch_symbol *isym = (struct arch_symbol *) sym;
811#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000812#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000813 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000814#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000815#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000816 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000817 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000818#if defined(CONFIG_USE_PLT_LIST)
819 struct arch_list_entry *pe;
820#else
821 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000822#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000823#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000824
825 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000826
Eric Andersencffd5022002-05-24 06:50:15 +0000827
828#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000829 case R_ARM_NONE:
830 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000831
Eric Andersen3b1a7442003-12-24 20:30:45 +0000832 case R_ARM_ABS32:
833 *loc += v;
834 break;
Miles Baderae28b042002-04-01 09:34:25 +0000835
Eric Andersen3b1a7442003-12-24 20:30:45 +0000836 case R_ARM_GOT32:
837 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000838
Eric Andersen3b1a7442003-12-24 20:30:45 +0000839 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000840 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
841 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000842 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000843
Eric Andersen3b1a7442003-12-24 20:30:45 +0000844 assert(got);
845 *loc += got - dot;
846 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000847
Eric Andersen3b1a7442003-12-24 20:30:45 +0000848 case R_ARM_PC24:
849 case R_ARM_PLT32:
850 goto bb_use_plt;
851
852 case R_ARM_GOTOFF: /* address relative to the got */
853 assert(got);
854 *loc += v - got;
855 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000856
Eric Andersenbf77f612003-01-23 06:02:39 +0000857#elif defined(__s390__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000858 case R_390_32:
859 *(unsigned int *) loc += v;
860 break;
861 case R_390_16:
862 *(unsigned short *) loc += v;
863 break;
864 case R_390_8:
865 *(unsigned char *) loc += v;
866 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000867
Eric Andersen3b1a7442003-12-24 20:30:45 +0000868 case R_390_PC32:
869 *(unsigned int *) loc += v - dot;
870 break;
871 case R_390_PC16DBL:
872 *(unsigned short *) loc += (v - dot) >> 1;
873 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000874 case R_390_PC16:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000875 *(unsigned short *) loc += v - dot;
876 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 case R_390_PLT32:
879 case R_390_PLT16DBL:
880 /* find the plt entry and initialize it. */
881 assert(isym != NULL);
882 pe = (struct arch_single_entry *) &isym->pltent;
883 assert(pe->allocated);
884 if (pe->inited == 0) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000885 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000886 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
887 ip[1] = 0x100607f1;
888 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
889 ip[2] = v - 2;
890 else
891 ip[2] = v;
892 pe->inited = 1;
893 }
Eric Andersenbf77f612003-01-23 06:02:39 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 /* Insert relative distance to target. */
896 v = plt + pe->offset - dot;
897 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
898 *(unsigned int *) loc = (unsigned int) v;
899 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
900 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
901 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000902
Eric Andersen3b1a7442003-12-24 20:30:45 +0000903 case R_390_GLOB_DAT:
904 case R_390_JMP_SLOT:
905 *loc = v;
906 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000907
Eric Andersen3b1a7442003-12-24 20:30:45 +0000908 case R_390_RELATIVE:
909 *loc += f->baseaddr;
910 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000911
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 case R_390_GOTPC:
913 assert(got != 0);
914 *(unsigned long *) loc += got - dot;
915 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000916
Eric Andersen3b1a7442003-12-24 20:30:45 +0000917 case R_390_GOT12:
918 case R_390_GOT16:
919 case R_390_GOT32:
920 assert(isym != NULL);
921 assert(got != 0);
922 if (!isym->gotent.inited)
923 {
924 isym->gotent.inited = 1;
925 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
926 }
927 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
928 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
929 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
930 *(unsigned short *) loc += isym->gotent.offset;
931 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
932 *(unsigned int *) loc += isym->gotent.offset;
933 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000934
Eric Andersen951df202003-10-21 06:45:29 +0000935#ifndef R_390_GOTOFF32
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000936#define R_390_GOTOFF32 R_390_GOTOFF
Eric Andersen951df202003-10-21 06:45:29 +0000937#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000938 case R_390_GOTOFF32:
939 assert(got != 0);
940 *loc += v - got;
941 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000942
Eric Andersencffd5022002-05-24 06:50:15 +0000943#elif defined(__i386__)
944
Eric Andersen3b1a7442003-12-24 20:30:45 +0000945 case R_386_NONE:
946 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000947
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 case R_386_32:
949 *loc += v;
950 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000951
Eric Andersen3b1a7442003-12-24 20:30:45 +0000952 case R_386_PLT32:
953 case R_386_PC32:
954 *loc += v - dot;
955 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000956
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 case R_386_GLOB_DAT:
958 case R_386_JMP_SLOT:
959 *loc = v;
960 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000961
Eric Andersen3b1a7442003-12-24 20:30:45 +0000962 case R_386_RELATIVE:
963 *loc += f->baseaddr;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GOTPC:
967 assert(got != 0);
968 *loc += got - dot;
969 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000970
Eric Andersen3b1a7442003-12-24 20:30:45 +0000971 case R_386_GOT32:
972 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_386_GOTOFF:
975 assert(got != 0);
976 *loc += v - got;
977 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000978
979#elif defined(__mc68000__)
980
Eric Andersen3b1a7442003-12-24 20:30:45 +0000981 case R_68K_NONE:
982 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000983
Eric Andersen3b1a7442003-12-24 20:30:45 +0000984 case R_68K_32:
985 *loc += v;
986 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000987
Eric Andersen3b1a7442003-12-24 20:30:45 +0000988 case R_68K_8:
989 if (v > 0xff) {
990 ret = obj_reloc_overflow;
991 }
992 *(char *)loc = v;
993 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000994
Eric Andersen3b1a7442003-12-24 20:30:45 +0000995 case R_68K_16:
996 if (v > 0xffff) {
997 ret = obj_reloc_overflow;
998 }
999 *(short *)loc = v;
1000 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001001
Eric Andersen3b1a7442003-12-24 20:30:45 +00001002 case R_68K_PC8:
1003 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001004 if ((Elf32_Sword)v > 0x7f ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001005 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1006 ret = obj_reloc_overflow;
1007 }
1008 *(char *)loc = v;
1009 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001010
Eric Andersen3b1a7442003-12-24 20:30:45 +00001011 case R_68K_PC16:
1012 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001013 if ((Elf32_Sword)v > 0x7fff ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001014 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1015 ret = obj_reloc_overflow;
1016 }
1017 *(short *)loc = v;
1018 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001019
Eric Andersen3b1a7442003-12-24 20:30:45 +00001020 case R_68K_PC32:
1021 *(int *)loc = v - dot;
1022 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001023
Eric Andersen3b1a7442003-12-24 20:30:45 +00001024 case R_68K_GLOB_DAT:
1025 case R_68K_JMP_SLOT:
1026 *loc = v;
1027 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001028
Eric Andersen3b1a7442003-12-24 20:30:45 +00001029 case R_68K_RELATIVE:
1030 *(int *)loc += f->baseaddr;
1031 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001032
Eric Andersen3b1a7442003-12-24 20:30:45 +00001033 case R_68K_GOT32:
1034 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001035
Eric Andersen16451a02004-03-19 12:16:18 +00001036#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001037 case R_68K_GOTOFF:
1038 assert(got != 0);
1039 *loc += v - got;
1040 break;
Eric Andersen16451a02004-03-19 12:16:18 +00001041#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001042
1043#elif defined(__mips__)
1044
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_MIPS_NONE:
1046 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001047
Eric Andersen3b1a7442003-12-24 20:30:45 +00001048 case R_MIPS_32:
1049 *loc += v;
1050 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_MIPS_26:
1053 if (v % 4)
1054 ret = obj_reloc_dangerous;
1055 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1056 ret = obj_reloc_overflow;
1057 *loc =
1058 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1059 0x03ffffff);
1060 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001061
Eric Andersen3b1a7442003-12-24 20:30:45 +00001062 case R_MIPS_HI16:
1063 {
1064 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001065
Eric Andersen3b1a7442003-12-24 20:30:45 +00001066 /* We cannot relocate this one now because we don't know the value
1067 of the carry we need to add. Save the information, and let LO16
1068 do the actual relocation. */
1069 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1070 n->addr = loc;
1071 n->value = v;
1072 n->next = ifile->mips_hi16_list;
1073 ifile->mips_hi16_list = n;
1074 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001075 }
1076
Eric Andersen3b1a7442003-12-24 20:30:45 +00001077 case R_MIPS_LO16:
1078 {
1079 unsigned long insnlo = *loc;
1080 Elf32_Addr val, vallo;
1081
1082 /* Sign extend the addend we extract from the lo insn. */
1083 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1084
1085 if (ifile->mips_hi16_list != NULL) {
1086 struct mips_hi16 *l;
1087
1088 l = ifile->mips_hi16_list;
1089 while (l != NULL) {
1090 struct mips_hi16 *next;
1091 unsigned long insn;
1092
1093 /* The value for the HI16 had best be the same. */
1094 assert(v == l->value);
1095
1096 /* Do the HI16 relocation. Note that we actually don't
1097 need to know anything about the LO16 itself, except where
1098 to find the low 16 bits of the addend needed by the LO16. */
1099 insn = *l->addr;
1100 val =
1101 ((insn & 0xffff) << 16) +
1102 vallo;
1103 val += v;
1104
1105 /* Account for the sign extension that will happen in the
1106 low bits. */
1107 val =
1108 ((val >> 16) +
1109 ((val & 0x8000) !=
1110 0)) & 0xffff;
1111
1112 insn = (insn & ~0xffff) | val;
1113 *l->addr = insn;
1114
1115 next = l->next;
1116 free(l);
1117 l = next;
1118 }
1119
1120 ifile->mips_hi16_list = NULL;
1121 }
1122
1123 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1124 val = v + vallo;
1125 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1126 *loc = insnlo;
1127 break;
1128 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001129
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001130#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001131
Eric Andersen3b1a7442003-12-24 20:30:45 +00001132 case R_PPC_ADDR16_HA:
1133 *(unsigned short *)loc = (v + 0x8000) >> 16;
1134 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001135
Eric Andersen3b1a7442003-12-24 20:30:45 +00001136 case R_PPC_ADDR16_HI:
1137 *(unsigned short *)loc = v >> 16;
1138 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001139
Eric Andersen3b1a7442003-12-24 20:30:45 +00001140 case R_PPC_ADDR16_LO:
1141 *(unsigned short *)loc = v;
1142 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001143
Eric Andersen3b1a7442003-12-24 20:30:45 +00001144 case R_PPC_REL24:
1145 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001146
Eric Andersen3b1a7442003-12-24 20:30:45 +00001147 case R_PPC_REL32:
1148 *loc = v - dot;
1149 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001150
Eric Andersen3b1a7442003-12-24 20:30:45 +00001151 case R_PPC_ADDR32:
1152 *loc = v;
1153 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001154
1155#elif defined(__sh__)
1156
Eric Andersen3b1a7442003-12-24 20:30:45 +00001157 case R_SH_NONE:
1158 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001159
Eric Andersen3b1a7442003-12-24 20:30:45 +00001160 case R_SH_DIR32:
1161 *loc += v;
1162 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001163
Eric Andersen3b1a7442003-12-24 20:30:45 +00001164 case R_SH_REL32:
1165 *loc += v - dot;
1166 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001167
Eric Andersen3b1a7442003-12-24 20:30:45 +00001168 case R_SH_PLT32:
1169 *loc = v - dot;
1170 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001171
Eric Andersen3b1a7442003-12-24 20:30:45 +00001172 case R_SH_GLOB_DAT:
1173 case R_SH_JMP_SLOT:
1174 *loc = v;
1175 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001176
Eric Andersen3b1a7442003-12-24 20:30:45 +00001177 case R_SH_RELATIVE:
1178 *loc = f->baseaddr + rel->r_addend;
1179 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001180
Eric Andersen3b1a7442003-12-24 20:30:45 +00001181 case R_SH_GOTPC:
1182 assert(got != 0);
1183 *loc = got - dot + rel->r_addend;
1184 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001185
Eric Andersen3b1a7442003-12-24 20:30:45 +00001186 case R_SH_GOT32:
1187 goto bb_use_got;
1188
1189 case R_SH_GOTOFF:
1190 assert(got != 0);
1191 *loc = v - got;
1192 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001193
Eric Andersenbf833552003-08-13 19:56:33 +00001194#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001195 case R_SH_IMM_MEDLOW16:
1196 case R_SH_IMM_LOW16:
1197 {
1198 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001199
Eric Andersen3b1a7442003-12-24 20:30:45 +00001200 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1201 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001202
Eric Andersen3b1a7442003-12-24 20:30:45 +00001203 /*
1204 * movi and shori have the format:
1205 *
1206 * | op | imm | reg | reserved |
1207 * 31..26 25..10 9.. 4 3 .. 0
1208 *
1209 * so we simply mask and or in imm.
1210 */
1211 word = *loc & ~0x3fffc00;
1212 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001213
Eric Andersen3b1a7442003-12-24 20:30:45 +00001214 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001215
Eric Andersen3b1a7442003-12-24 20:30:45 +00001216 break;
1217 }
Eric Andersenbf833552003-08-13 19:56:33 +00001218
Eric Andersen3b1a7442003-12-24 20:30:45 +00001219 case R_SH_IMM_MEDLOW16_PCREL:
1220 case R_SH_IMM_LOW16_PCREL:
1221 {
1222 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001223
Eric Andersen3b1a7442003-12-24 20:30:45 +00001224 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001225
Eric Andersen3b1a7442003-12-24 20:30:45 +00001226 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001227
Eric Andersen3b1a7442003-12-24 20:30:45 +00001228 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1229 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001230
Eric Andersen3b1a7442003-12-24 20:30:45 +00001231 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001232
Eric Andersen3b1a7442003-12-24 20:30:45 +00001233 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001234
Eric Andersen3b1a7442003-12-24 20:30:45 +00001235 break;
1236 }
Eric Andersenbf833552003-08-13 19:56:33 +00001237#endif /* __SH5__ */
1238#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001239
Eric Andersen3b1a7442003-12-24 20:30:45 +00001240 default:
1241 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1242 ret = obj_reloc_unhandled;
1243 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001244
1245#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001246 case R_V850_NONE:
1247 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001248
Eric Andersen3b1a7442003-12-24 20:30:45 +00001249 case R_V850_32:
1250 /* We write two shorts instead of a long because even
1251 32-bit insns only need half-word alignment, but
1252 32-bit data needs to be long-word aligned. */
1253 v += ((unsigned short *)loc)[0];
1254 v += ((unsigned short *)loc)[1] << 16;
1255 ((unsigned short *)loc)[0] = v & 0xffff;
1256 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1257 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001258
Eric Andersen3b1a7442003-12-24 20:30:45 +00001259 case R_V850_22_PCREL:
1260 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001261#endif
1262
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001263#if defined (__cris__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001264 case R_CRIS_NONE:
1265 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001266
Eric Andersen3b1a7442003-12-24 20:30:45 +00001267 case R_CRIS_32:
1268 /* CRIS keeps the relocation value in the r_addend field and
1269 * should not use whats in *loc at all
1270 */
1271 *loc = v;
1272 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001273#endif
1274
Eric Andersena6f6a952004-05-26 12:06:38 +00001275#if defined(__H8300H__) || defined(__H8300S__)
Eric Andersenee70fa52004-05-26 11:38:46 +00001276 case R_H8_DIR24R8:
1277 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
1278 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
1279 break;
1280 case R_H8_DIR24A8:
1281 *loc += v;
1282 break;
1283 case R_H8_DIR32:
1284 case R_H8_DIR32A16:
1285 *loc += v;
1286 break;
1287 case R_H8_PCREL16:
1288 v -= dot + 2;
1289 if ((Elf32_Sword)v > 0x7fff ||
1290 (Elf32_Sword)v < -(Elf32_Sword)0x8000)
1291 ret = obj_reloc_overflow;
1292 else
1293 *(unsigned short *)loc = v;
1294 break;
1295 case R_H8_PCREL8:
1296 v -= dot + 1;
1297 if ((Elf32_Sword)v > 0x7f ||
1298 (Elf32_Sword)v < -(Elf32_Sword)0x80)
1299 ret = obj_reloc_overflow;
1300 else
1301 *(unsigned char *)loc = v;
1302 break;
1303#endif
1304
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001305#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001306
Eric Andersen3b1a7442003-12-24 20:30:45 +00001307bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001308
Eric Andersen3b1a7442003-12-24 20:30:45 +00001309 /* find the plt entry and initialize it if necessary */
1310 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001311
Eric Andersencffd5022002-05-24 06:50:15 +00001312#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001313 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1314 pe = pe->next;
1315 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001316#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001317 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001318#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001319
Eric Andersen3b1a7442003-12-24 20:30:45 +00001320 if (! pe->inited) {
1321 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001322
Eric Andersen3b1a7442003-12-24 20:30:45 +00001323 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001324
1325#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001326 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1327 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001328#endif
1329#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001330 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1331 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1332 ip[2] = 0x7d6903a6; /* mtctr r11 */
1333 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001334#endif
Miles Baderae28b042002-04-01 09:34:25 +00001335#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001336 /* We have to trash a register, so we assume that any control
1337 transfer more than 21-bits away must be a function call
1338 (so we can use a call-clobbered register). */
1339 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1340 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001341#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001342 pe->inited = 1;
1343 }
Eric Andersen21adca72000-12-06 18:18:26 +00001344
Eric Andersen3b1a7442003-12-24 20:30:45 +00001345 /* relative distance to target */
1346 v -= dot;
1347 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001348#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001349 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001350#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001351 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001352#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001353 /* go via the plt */
1354 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001355
1356#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001358#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001359 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001360#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001361 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001362
Eric Andersen3b1a7442003-12-24 20:30:45 +00001363 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001364#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001365 /* Convert to words. */
1366 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001367
Eric Andersen3b1a7442003-12-24 20:30:45 +00001368 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001369#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001370#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001371 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001372#endif
Miles Baderae28b042002-04-01 09:34:25 +00001373#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001374 /* We write two shorts instead of a long because even 32-bit insns
1375 only need half-word alignment, but the 32-bit data write needs
1376 to be long-word aligned. */
1377 ((unsigned short *)loc)[0] =
1378 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1379 | ((v >> 16) & 0x3f); /* offs high part */
1380 ((unsigned short *)loc)[1] =
1381 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001382#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001383 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001384#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001385
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001386#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001387bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001388
Eric Andersen3b1a7442003-12-24 20:30:45 +00001389 assert(isym != NULL);
1390 /* needs an entry in the .got: set it, once */
1391 if (!isym->gotent.inited) {
1392 isym->gotent.inited = 1;
1393 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1394 }
1395 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001396#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001397 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001398#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001399 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001400#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001401 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001402
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001403#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001404 }
1405
1406 return ret;
1407}
1408
Eric Andersencffd5022002-05-24 06:50:15 +00001409
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001410#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001411
1412static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1413 int offset, int size)
1414{
1415 struct arch_list_entry *pe;
1416
1417 for (pe = *list; pe != NULL; pe = pe->next) {
1418 if (pe->addend == rel->r_addend) {
1419 break;
1420 }
1421 }
1422
1423 if (pe == NULL) {
1424 pe = xmalloc(sizeof(struct arch_list_entry));
1425 pe->next = *list;
1426 pe->addend = rel->r_addend;
1427 pe->offset = offset;
1428 pe->inited = 0;
1429 *list = pe;
1430 return size;
1431 }
1432 return 0;
1433}
1434
1435#endif
1436
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001437#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001438
1439static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1440 int offset, int size)
1441{
1442 if (single->allocated == 0) {
1443 single->allocated = 1;
1444 single->offset = offset;
1445 single->inited = 0;
1446 return size;
1447 }
1448 return 0;
1449}
1450
1451#endif
1452
1453#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1454
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001455static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001456 int offset, int size)
1457{
1458 struct obj_section *myrelsec = obj_find_section(f, name);
1459
1460 if (offset == 0) {
1461 offset += size;
1462 }
1463
1464 if (myrelsec) {
1465 obj_extend_section(myrelsec, offset);
1466 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001467 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001469 assert(myrelsec);
1470 }
1471
1472 return myrelsec;
1473}
1474
1475#endif
1476
1477static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001478{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001479#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001480 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001481 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001482#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001483 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001484#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001485#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001486 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001487#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001489 ElfW(RelM) *rel, *relend;
1490 ElfW(Sym) *symtab, *extsym;
1491 const char *strtab, *name;
1492 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001493
Eric Andersen21adca72000-12-06 18:18:26 +00001494 for (i = 0; i < f->header.e_shnum; ++i) {
1495 relsec = f->sections[i];
1496 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001497 continue;
1498
Eric Andersen21adca72000-12-06 18:18:26 +00001499 symsec = f->sections[relsec->header.sh_link];
1500 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001501
Eric Andersen21adca72000-12-06 18:18:26 +00001502 rel = (ElfW(RelM) *) relsec->contents;
1503 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1504 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001505 strtab = (const char *) strsec->contents;
1506
1507 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001508 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001509
Eric Andersencffd5022002-05-24 06:50:15 +00001510#if defined(CONFIG_USE_GOT_ENTRIES)
1511 got_allocate = 0;
1512#endif
1513#if defined(CONFIG_USE_PLT_ENTRIES)
1514 plt_allocate = 0;
1515#endif
1516
Eric Andersen9f16d612000-06-12 23:11:16 +00001517 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001518#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 case R_ARM_PC24:
1520 case R_ARM_PLT32:
1521 plt_allocate = 1;
1522 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001523
Eric Andersen3b1a7442003-12-24 20:30:45 +00001524 case R_ARM_GOTOFF:
1525 case R_ARM_GOTPC:
1526 got_needed = 1;
1527 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001528
Eric Andersen3b1a7442003-12-24 20:30:45 +00001529 case R_ARM_GOT32:
1530 got_allocate = 1;
1531 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001532
Eric Andersen21adca72000-12-06 18:18:26 +00001533#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001534 case R_386_GOTPC:
1535 case R_386_GOTOFF:
1536 got_needed = 1;
1537 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001538
Eric Andersen3b1a7442003-12-24 20:30:45 +00001539 case R_386_GOT32:
1540 got_allocate = 1;
1541 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001542
1543#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001544 case R_PPC_REL24:
1545 plt_allocate = 1;
1546 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001547
1548#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001549 case R_68K_GOT32:
1550 got_allocate = 1;
1551 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001552
Eric Andersen16451a02004-03-19 12:16:18 +00001553#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001554 case R_68K_GOTOFF:
1555 got_needed = 1;
1556 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001557#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001558
1559#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001560 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001561 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001562 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001563
Eric Andersen3b1a7442003-12-24 20:30:45 +00001564 case R_SH_GOTPC:
1565 case R_SH_GOTOFF:
1566 got_needed = 1;
1567 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001568
1569#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001570 case R_V850_22_PCREL:
1571 plt_needed = 1;
1572 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001573
1574#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001575 default:
1576 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001577 }
1578
Eric Andersen21adca72000-12-06 18:18:26 +00001579 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001580 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001581 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001582 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001583 }
1584 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001585#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001586 if (got_allocate) {
1587 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001588 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001589 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001590
1591 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001592 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001593#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001594#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001595 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001596#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001597 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001598 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001599 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001600#else
1601 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001602 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001603 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001604#endif
1605 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001606 }
1607#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001608 }
Miles Baderae28b042002-04-01 09:34:25 +00001609 }
Eric Andersen21adca72000-12-06 18:18:26 +00001610
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001611#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001612 if (got_needed) {
1613 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001614 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001615 }
Eric Andersen21adca72000-12-06 18:18:26 +00001616#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001617
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001618#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001619 if (plt_needed) {
1620 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001621 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001622 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001623#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001624
1625#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001626}
1627
Eric Andersen9f16d612000-06-12 23:11:16 +00001628/*======================================================================*/
1629
1630/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001631static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001632{
1633 unsigned long h = 0;
1634 unsigned long g;
1635 unsigned char ch;
1636
1637 while (n > 0) {
1638 ch = *name++;
1639 h = (h << 4) + ch;
1640 if ((g = (h & 0xf0000000)) != 0) {
1641 h ^= g >> 24;
1642 h &= ~g;
1643 }
1644 n--;
1645 }
1646 return h;
1647}
1648
Eric Andersen044228d2001-07-17 01:12:36 +00001649static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001650{
1651 return obj_elf_hash_n(name, strlen(name));
1652}
1653
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001654#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001655/* String comparison for non-co-versioned kernel and module. */
1656
1657static int ncv_strcmp(const char *a, const char *b)
1658{
1659 size_t alen = strlen(a), blen = strlen(b);
1660
1661 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1662 return strncmp(a, b, alen);
1663 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1664 return strncmp(a, b, blen);
1665 else
1666 return strcmp(a, b);
1667}
1668
1669/* String hashing for non-co-versioned kernel and module. Here
1670 we are simply forced to drop the crc from the hash. */
1671
1672static unsigned long ncv_symbol_hash(const char *str)
1673{
1674 size_t len = strlen(str);
1675 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1676 len -= 10;
1677 return obj_elf_hash_n(str, len);
1678}
1679
Eric Andersen044228d2001-07-17 01:12:36 +00001680static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001681obj_set_symbol_compare(struct obj_file *f,
1682 int (*cmp) (const char *, const char *),
1683 unsigned long (*hash) (const char *))
1684{
1685 if (cmp)
1686 f->symbol_cmp = cmp;
1687 if (hash) {
1688 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1689 int i;
1690
1691 f->symbol_hash = hash;
1692
1693 memcpy(tmptab, f->symtab, sizeof(tmptab));
1694 memset(f->symtab, 0, sizeof(f->symtab));
1695
1696 for (i = 0; i < HASH_BUCKETS; ++i)
1697 for (sym = tmptab[i]; sym; sym = next) {
1698 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1699 next = sym->next;
1700 sym->next = f->symtab[h];
1701 f->symtab[h] = sym;
1702 }
1703 }
1704}
1705
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001706#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001707
Eric Andersen044228d2001-07-17 01:12:36 +00001708static struct obj_symbol *
1709obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001710 unsigned long symidx, int info,
1711 int secidx, ElfW(Addr) value,
1712 unsigned long size)
1713{
1714 struct obj_symbol *sym;
1715 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1716 int n_type = ELFW(ST_TYPE) (info);
1717 int n_binding = ELFW(ST_BIND) (info);
1718
1719 for (sym = f->symtab[hash]; sym; sym = sym->next)
1720 if (f->symbol_cmp(sym->name, name) == 0) {
1721 int o_secidx = sym->secidx;
1722 int o_info = sym->info;
1723 int o_type = ELFW(ST_TYPE) (o_info);
1724 int o_binding = ELFW(ST_BIND) (o_info);
1725
1726 /* A redefinition! Is it legal? */
1727
1728 if (secidx == SHN_UNDEF)
1729 return sym;
1730 else if (o_secidx == SHN_UNDEF)
1731 goto found;
1732 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1733 /* Cope with local and global symbols of the same name
1734 in the same object file, as might have been created
1735 by ld -r. The only reason locals are now seen at this
1736 level at all is so that we can do semi-sensible things
1737 with parameters. */
1738
1739 struct obj_symbol *nsym, **p;
1740
1741 nsym = arch_new_symbol();
1742 nsym->next = sym->next;
1743 nsym->ksymidx = -1;
1744
1745 /* Excise the old (local) symbol from the hash chain. */
1746 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1747 continue;
1748 *p = sym = nsym;
1749 goto found;
1750 } else if (n_binding == STB_LOCAL) {
1751 /* Another symbol of the same name has already been defined.
1752 Just add this to the local table. */
1753 sym = arch_new_symbol();
1754 sym->next = NULL;
1755 sym->ksymidx = -1;
1756 f->local_symtab[symidx] = sym;
1757 goto found;
1758 } else if (n_binding == STB_WEAK)
1759 return sym;
1760 else if (o_binding == STB_WEAK)
1761 goto found;
1762 /* Don't unify COMMON symbols with object types the programmer
1763 doesn't expect. */
1764 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001765 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001766 return sym;
1767 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001768 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001769 goto found;
1770 else {
1771 /* Don't report an error if the symbol is coming from
1772 the kernel or some external module. */
1773 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001774 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001775 return sym;
1776 }
1777 }
1778
1779 /* Completely new symbol. */
1780 sym = arch_new_symbol();
1781 sym->next = f->symtab[hash];
1782 f->symtab[hash] = sym;
1783 sym->ksymidx = -1;
1784
Eric Andersen66ca9482001-06-28 21:36:06 +00001785 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1786 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001787 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001788 name, (long) symidx, (long) f->local_symtab_size);
1789 else
1790 f->local_symtab[symidx] = sym;
1791 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001792
Eric Andersen3b1a7442003-12-24 20:30:45 +00001793found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001794 sym->name = name;
1795 sym->value = value;
1796 sym->size = size;
1797 sym->secidx = secidx;
1798 sym->info = info;
1799
1800 return sym;
1801}
1802
Eric Andersen044228d2001-07-17 01:12:36 +00001803static struct obj_symbol *
1804obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001805{
1806 struct obj_symbol *sym;
1807 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1808
1809 for (sym = f->symtab[hash]; sym; sym = sym->next)
1810 if (f->symbol_cmp(sym->name, name) == 0)
1811 return sym;
1812
1813 return NULL;
1814}
1815
Eric Andersen044228d2001-07-17 01:12:36 +00001816static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001817 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1818{
1819 if (sym) {
1820 if (sym->secidx >= SHN_LORESERVE)
1821 return sym->value;
1822
1823 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1824 } else {
1825 /* As a special case, a NULL sym has value zero. */
1826 return 0;
1827 }
1828}
1829
Eric Andersen044228d2001-07-17 01:12:36 +00001830static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001831{
1832 int i, n = f->header.e_shnum;
1833
1834 for (i = 0; i < n; ++i)
1835 if (strcmp(f->sections[i]->name, name) == 0)
1836 return f->sections[i];
1837
1838 return NULL;
1839}
1840
1841static int obj_load_order_prio(struct obj_section *a)
1842{
1843 unsigned long af, ac;
1844
1845 af = a->header.sh_flags;
1846
1847 ac = 0;
1848 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001849 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001850 ac |= 32;
1851 if (af & SHF_ALLOC)
1852 ac |= 16;
1853 if (!(af & SHF_WRITE))
1854 ac |= 8;
1855 if (af & SHF_EXECINSTR)
1856 ac |= 4;
1857 if (a->header.sh_type != SHT_NOBITS)
1858 ac |= 2;
1859
1860 return ac;
1861}
1862
Eric Andersen044228d2001-07-17 01:12:36 +00001863static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001864obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1865{
1866 struct obj_section **p;
1867 int prio = obj_load_order_prio(sec);
1868 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1869 if (obj_load_order_prio(*p) < prio)
1870 break;
1871 sec->load_next = *p;
1872 *p = sec;
1873}
1874
Eric Andersen044228d2001-07-17 01:12:36 +00001875static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001876 const char *name,
1877 unsigned long align,
1878 unsigned long size)
1879{
1880 int newidx = f->header.e_shnum++;
1881 struct obj_section *sec;
1882
1883 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1884 f->sections[newidx] = sec = arch_new_section();
1885
1886 memset(sec, 0, sizeof(*sec));
1887 sec->header.sh_type = SHT_PROGBITS;
1888 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1889 sec->header.sh_size = size;
1890 sec->header.sh_addralign = align;
1891 sec->name = name;
1892 sec->idx = newidx;
1893 if (size)
1894 sec->contents = xmalloc(size);
1895
1896 obj_insert_section_load_order(f, sec);
1897
1898 return sec;
1899}
1900
Eric Andersen044228d2001-07-17 01:12:36 +00001901static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001902 const char *name,
1903 unsigned long align,
1904 unsigned long size)
1905{
1906 int newidx = f->header.e_shnum++;
1907 struct obj_section *sec;
1908
1909 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1910 f->sections[newidx] = sec = arch_new_section();
1911
1912 memset(sec, 0, sizeof(*sec));
1913 sec->header.sh_type = SHT_PROGBITS;
1914 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1915 sec->header.sh_size = size;
1916 sec->header.sh_addralign = align;
1917 sec->name = name;
1918 sec->idx = newidx;
1919 if (size)
1920 sec->contents = xmalloc(size);
1921
1922 sec->load_next = f->load_order;
1923 f->load_order = sec;
1924 if (f->load_order_search_start == &f->load_order)
1925 f->load_order_search_start = &sec->load_next;
1926
1927 return sec;
1928}
1929
Eric Andersen044228d2001-07-17 01:12:36 +00001930static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001931{
1932 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001933 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001934 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1935 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001936 return sec->contents + oldsize;
1937}
1938
1939
Eric Andersen9f16d612000-06-12 23:11:16 +00001940/* Conditionally add the symbols from the given symbol set to the
1941 new module. */
1942
1943static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00001944add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001945 int idx, struct new_module_symbol *syms, size_t nsyms)
1946{
1947 struct new_module_symbol *s;
1948 size_t i;
1949 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001950#ifdef SYMBOL_PREFIX
1951 char *name_buf = 0;
1952 size_t name_alloced_size = 0;
1953#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001954#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
1955 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00001956
Glenn L McGrath759515c2003-08-30 06:00:33 +00001957 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001958#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001959 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001960 /* Only add symbols that are already marked external.
1961 If we override locals we may cause problems for
1962 argument initialization. We will also create a false
1963 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001964 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001965 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00001966
Glenn L McGrath759515c2003-08-30 06:00:33 +00001967 /* GPL licensed modules can use symbols exported with
1968 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
1969 * exported names. Non-GPL modules never see any GPLONLY_
1970 * symbols so they cannot fudge it by adding the prefix on
1971 * their references.
1972 */
1973 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001974#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00001975 if (gpl)
1976 ((char *)s->name) += 8;
1977 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001978#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00001979 continue;
1980 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001981 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00001982
Miles Baderae28b042002-04-01 09:34:25 +00001983#ifdef SYMBOL_PREFIX
1984 /* Prepend SYMBOL_PREFIX to the symbol's name (the
1985 kernel exports `C names', but module object files
1986 reference `linker names'). */
1987 size_t extra = sizeof SYMBOL_PREFIX;
1988 size_t name_size = strlen (name) + extra;
1989 if (name_size > name_alloced_size) {
1990 name_alloced_size = name_size * 2;
1991 name_buf = alloca (name_alloced_size);
1992 }
1993 strcpy (name_buf, SYMBOL_PREFIX);
1994 strcpy (name_buf + extra - 1, name);
1995 name = name_buf;
1996#endif /* SYMBOL_PREFIX */
1997
1998 sym = obj_find_symbol(f, name);
1999 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
2000#ifdef SYMBOL_PREFIX
2001 /* Put NAME_BUF into more permanent storage. */
2002 name = xmalloc (name_size);
2003 strcpy (name, name_buf);
2004#endif
2005 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002006 ELFW(ST_INFO) (STB_GLOBAL,
2007 STT_NOTYPE),
2008 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002009 /* Did our symbol just get installed? If so, mark the
2010 module as "used". */
2011 if (sym->secidx == idx)
2012 used = 1;
2013 }
2014 }
2015
2016 return used;
2017}
2018
2019static void add_kernel_symbols(struct obj_file *f)
2020{
2021 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002022 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002023
2024 /* Add module symbols first. */
2025
2026 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2027 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002028 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2029 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002030
2031 n_ext_modules_used = nused;
2032
2033 /* And finally the symbols from the kernel proper. */
2034
2035 if (nksyms)
2036 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2037}
2038
2039static char *get_modinfo_value(struct obj_file *f, const char *key)
2040{
2041 struct obj_section *sec;
2042 char *p, *v, *n, *ep;
2043 size_t klen = strlen(key);
2044
2045 sec = obj_find_section(f, ".modinfo");
2046 if (sec == NULL)
2047 return NULL;
2048 p = sec->contents;
2049 ep = p + sec->header.sh_size;
2050 while (p < ep) {
2051 v = strchr(p, '=');
2052 n = strchr(p, '\0');
2053 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002054 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002055 return v + 1;
2056 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002057 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002058 return n;
2059 }
2060 p = n + 1;
2061 }
2062
2063 return NULL;
2064}
2065
2066
2067/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002068/* Functions relating to module loading after 2.1.18. */
2069
2070static int
2071new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2072{
2073 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002074 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002075 struct obj_symbol *sym;
2076 char *contents, *loc;
2077 int min, max, n;
2078
2079 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002080 if ((q = strchr(p, '=')) == NULL) {
2081 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002082 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002083 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002084
2085 key = alloca(q - p + 6);
2086 memcpy(key, "parm_", 5);
2087 memcpy(key + 5, p, q - p);
2088 key[q - p + 5] = 0;
2089
2090 p = get_modinfo_value(f, key);
2091 key += 5;
2092 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002093 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002094 return 0;
2095 }
2096
Miles Baderae28b042002-04-01 09:34:25 +00002097#ifdef SYMBOL_PREFIX
2098 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2099 strcpy (sym_name, SYMBOL_PREFIX);
2100 strcat (sym_name, key);
2101#else
2102 sym_name = key;
2103#endif
2104 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002105
2106 /* Also check that the parameter was not resolved from the kernel. */
2107 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002108 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002109 return 0;
2110 }
2111
2112 if (isdigit(*p)) {
2113 min = strtoul(p, &p, 10);
2114 if (*p == '-')
2115 max = strtoul(p + 1, &p, 10);
2116 else
2117 max = min;
2118 } else
2119 min = max = 1;
2120
2121 contents = f->sections[sym->secidx]->contents;
2122 loc = contents + sym->value;
2123 n = (*++q != '\0');
2124
2125 while (1) {
2126 if ((*p == 's') || (*p == 'c')) {
2127 char *str;
2128
2129 /* Do C quoting if we begin with a ", else slurp the lot. */
2130 if (*q == '"') {
2131 char *r;
2132
2133 str = alloca(strlen(q));
2134 for (r = str, q++; *q != '"'; ++q, ++r) {
2135 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002136 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002137 key);
2138 return 0;
2139 } else if (*q == '\\')
2140 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002141 case 'a':
2142 *r = '\a';
2143 break;
2144 case 'b':
2145 *r = '\b';
2146 break;
2147 case 'e':
2148 *r = '\033';
2149 break;
2150 case 'f':
2151 *r = '\f';
2152 break;
2153 case 'n':
2154 *r = '\n';
2155 break;
2156 case 'r':
2157 *r = '\r';
2158 break;
2159 case 't':
2160 *r = '\t';
2161 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002162
Eric Andersen3b1a7442003-12-24 20:30:45 +00002163 case '0':
2164 case '1':
2165 case '2':
2166 case '3':
2167 case '4':
2168 case '5':
2169 case '6':
2170 case '7':
2171 {
2172 int c = *q - '0';
2173 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002174 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002175 if (q[1] >= '0' && q[1] <= '7')
2176 c = (c * 8) + *++q - '0';
2177 }
2178 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002179 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002180 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002181
Eric Andersen3b1a7442003-12-24 20:30:45 +00002182 default:
2183 *r = *q;
2184 break;
2185 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002186 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002187 }
2188 *r = '\0';
2189 ++q;
2190 } else {
2191 char *r;
2192
2193 /* In this case, the string is not quoted. We will break
2194 it using the coma (like for ints). If the user wants to
2195 include comas in a string, he just has to quote it */
2196
2197 /* Search the next coma */
2198 r = strchr(q, ',');
2199
2200 /* Found ? */
2201 if (r != (char *) NULL) {
2202 /* Recopy the current field */
2203 str = alloca(r - q + 1);
2204 memcpy(str, q, r - q);
2205
Eric Andersenaff114c2004-04-14 17:51:38 +00002206 /* I don't know if it is useful, as the previous case
2207 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002208 str[r - q] = '\0';
2209
2210 /* Keep next fields */
2211 q = r;
2212 } else {
2213 /* last string */
2214 str = q;
2215 q = "";
2216 }
2217 }
2218
2219 if (*p == 's') {
2220 /* Normal string */
2221 obj_string_patch(f, sym->secidx, loc - contents, str);
2222 loc += tgt_sizeof_char_p;
2223 } else {
2224 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002225 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002226
2227 /* Get the size of each member */
2228 /* Probably we should do that outside the loop ? */
2229 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002230 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002231 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002232 return 0;
2233 }
2234 charssize = strtoul(p + 1, (char **) NULL, 10);
2235
2236 /* Check length */
2237 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002238 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002239 charssize - 1);
2240 return 0;
2241 }
2242
2243 /* Copy to location */
2244 strcpy((char *) loc, str);
2245 loc += charssize;
2246 }
2247 } else {
2248 long v = strtoul(q, &q, 0);
2249 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002250 case 'b':
2251 *loc++ = v;
2252 break;
2253 case 'h':
2254 *(short *) loc = v;
2255 loc += tgt_sizeof_short;
2256 break;
2257 case 'i':
2258 *(int *) loc = v;
2259 loc += tgt_sizeof_int;
2260 break;
2261 case 'l':
2262 *(long *) loc = v;
2263 loc += tgt_sizeof_long;
2264 break;
2265
2266 default:
2267 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2268 return 0;
2269 }
2270 }
2271
2272retry_end_of_value:
2273 switch (*q) {
2274 case '\0':
2275 goto end_of_arg;
2276
2277 case ' ':
2278 case '\t':
2279 case '\n':
2280 case '\r':
2281 ++q;
2282 goto retry_end_of_value;
2283
2284 case ',':
2285 if (++n > max) {
2286 bb_error_msg("too many values for %s (max %d)", key, max);
2287 return 0;
2288 }
2289 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002290 break;
2291
2292 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002293 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002294 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002295 }
2296 }
2297
Eric Andersen3b1a7442003-12-24 20:30:45 +00002298end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002299 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002300 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002301 return 0;
2302 }
2303
2304 argc--, argv++;
2305 }
2306
2307 return 1;
2308}
2309
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002310#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002311static int new_is_module_checksummed(struct obj_file *f)
2312{
2313 const char *p = get_modinfo_value(f, "using_checksums");
2314 if (p)
2315 return atoi(p);
2316 else
2317 return 0;
2318}
2319
2320/* Get the module's kernel version in the canonical integer form. */
2321
2322static int
2323new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2324{
2325 char *p, *q;
2326 int a, b, c;
2327
2328 p = get_modinfo_value(f, "kernel_version");
2329 if (p == NULL)
2330 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002331 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002332
2333 a = strtoul(p, &p, 10);
2334 if (*p != '.')
2335 return -1;
2336 b = strtoul(p + 1, &p, 10);
2337 if (*p != '.')
2338 return -1;
2339 c = strtoul(p + 1, &q, 10);
2340 if (p + 1 == q)
2341 return -1;
2342
2343 return a << 16 | b << 8 | c;
2344}
2345
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002346#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002347
2348
Eric Andersen9f16d612000-06-12 23:11:16 +00002349/* Fetch the loaded modules, and all currently exported symbols. */
2350
2351static int new_get_kernel_symbols(void)
2352{
2353 char *module_names, *mn;
2354 struct external_module *modules, *m;
2355 struct new_module_symbol *syms, *s;
2356 size_t ret, bufsize, nmod, nsyms, i, j;
2357
2358 /* Collect the loaded modules. */
2359
2360 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002361retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002362 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002363 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002364 module_names = xrealloc(module_names, bufsize = ret);
2365 goto retry_modules_load;
2366 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002367 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002368 return 0;
2369 }
2370
2371 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002372
2373 /* Collect the modules' symbols. */
2374
Mark Whitley94fd4802001-03-12 23:08:34 +00002375 if (nmod){
2376 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2377 memset(modules, 0, nmod * sizeof(*modules));
2378 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002379 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002380 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002381
Mark Whitley94fd4802001-03-12 23:08:34 +00002382 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2383 if (errno == ENOENT) {
2384 /* The module was removed out from underneath us. */
2385 continue;
2386 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002387 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002388 return 0;
2389 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002390
Mark Whitley94fd4802001-03-12 23:08:34 +00002391 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002392retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002393 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2394 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002395 case ENOSPC:
2396 syms = xrealloc(syms, bufsize = ret);
2397 goto retry_mod_sym_load;
2398 case ENOENT:
2399 /* The module was removed out from underneath us. */
2400 continue;
2401 default:
2402 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2403 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002404 }
2405 }
2406 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002407
Mark Whitley94fd4802001-03-12 23:08:34 +00002408 m->name = mn;
2409 m->addr = info.addr;
2410 m->nsyms = nsyms;
2411 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002412
Mark Whitley94fd4802001-03-12 23:08:34 +00002413 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2414 s->name += (unsigned long) syms;
2415 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002416 }
2417 }
2418
2419 /* Collect the kernel's symbols. */
2420
2421 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002422retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002423 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002424 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002425 syms = xrealloc(syms, bufsize = ret);
2426 goto retry_kern_sym_load;
2427 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002428 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002429 return 0;
2430 }
2431 nksyms = nsyms = ret;
2432 ksyms = syms;
2433
2434 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2435 s->name += (unsigned long) syms;
2436 }
2437 return 1;
2438}
2439
2440
2441/* Return the kernel symbol checksum version, or zero if not used. */
2442
2443static int new_is_kernel_checksummed(void)
2444{
2445 struct new_module_symbol *s;
2446 size_t i;
2447
2448 /* Using_Versions is not the first symbol, but it should be in there. */
2449
2450 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2451 if (strcmp((char *) s->name, "Using_Versions") == 0)
2452 return s->value;
2453
2454 return 0;
2455}
2456
2457
2458static int new_create_this_module(struct obj_file *f, const char *m_name)
2459{
2460 struct obj_section *sec;
2461
2462 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002463 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002464 memset(sec->contents, 0, sizeof(struct new_module));
2465
Miles Baderae28b042002-04-01 09:34:25 +00002466 obj_add_symbol(f, SPFX "__this_module", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002467 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2468 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002469
2470 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002471 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002472
2473 return 1;
2474}
2475
Eric Andersen889dd202003-01-23 04:48:34 +00002476#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2477/* add an entry to the __ksymtab section, creating it if necessary */
2478static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2479{
2480 struct obj_section *sec;
2481 ElfW(Addr) ofs;
2482
2483 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2484 * If __ksymtab is defined but not marked alloc, x out the first character
2485 * (no obj_delete routine) and create a new __ksymtab with the correct
2486 * characteristics.
2487 */
2488 sec = obj_find_section(f, "__ksymtab");
2489 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2490 *((char *)(sec->name)) = 'x'; /* override const */
2491 sec = NULL;
2492 }
2493 if (!sec)
2494 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002495 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002496 if (!sec)
2497 return;
2498 sec->header.sh_flags |= SHF_ALLOC;
2499 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002500 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002501 ofs = sec->header.sh_size;
2502 obj_symbol_patch(f, sec->idx, ofs, sym);
2503 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2504 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2505}
2506#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002507
2508static int new_create_module_ksymtab(struct obj_file *f)
2509{
2510 struct obj_section *sec;
2511 int i;
2512
2513 /* We must always add the module references. */
2514
2515 if (n_ext_modules_used) {
2516 struct new_module_ref *dep;
2517 struct obj_symbol *tm;
2518
2519 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002520 (sizeof(struct new_module_ref)
2521 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002522 if (!sec)
2523 return 0;
2524
Miles Baderae28b042002-04-01 09:34:25 +00002525 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002526 dep = (struct new_module_ref *) sec->contents;
2527 for (i = 0; i < n_ext_modules; ++i)
2528 if (ext_modules[i].used) {
2529 dep->dep = ext_modules[i].addr;
2530 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002531 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002532 dep->next_ref = 0;
2533 ++dep;
2534 }
2535 }
2536
2537 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2538 size_t nsyms;
2539 int *loaded;
2540
2541 sec =
2542 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002543 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002544
2545 /* We don't want to export symbols residing in sections that
2546 aren't loaded. There are a number of these created so that
2547 we make sure certain module options don't appear twice. */
2548
2549 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2550 while (--i >= 0)
2551 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2552
2553 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2554 struct obj_symbol *sym;
2555 for (sym = f->symtab[i]; sym; sym = sym->next)
2556 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002557 && sym->secidx <= SHN_HIRESERVE
2558 && (sym->secidx >= SHN_LORESERVE
2559 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2561
2562 obj_symbol_patch(f, sec->idx, ofs, sym);
2563 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002564 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002565
2566 nsyms++;
2567 }
2568 }
2569
2570 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2571 }
2572
2573 return 1;
2574}
2575
2576
2577static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002578new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002579{
2580 struct new_module *module;
2581 struct obj_section *sec;
2582 void *image;
2583 int ret;
2584 tgt_long m_addr;
2585
2586 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002587 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002588 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002589 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002590 module = (struct new_module *) sec->contents;
2591 m_addr = sec->header.sh_addr;
2592
2593 module->size_of_struct = sizeof(*module);
2594 module->size = m_size;
2595 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2596
2597 sec = obj_find_section(f, "__ksymtab");
2598 if (sec && sec->header.sh_size) {
2599 module->syms = sec->header.sh_addr;
2600 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2601 }
2602
2603 if (n_ext_modules_used) {
2604 sec = obj_find_section(f, ".kmodtab");
2605 module->deps = sec->header.sh_addr;
2606 module->ndeps = n_ext_modules_used;
2607 }
2608
2609 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002610 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002611 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002612 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002613
2614 sec = obj_find_section(f, "__ex_table");
2615 if (sec) {
2616 module->ex_table_start = sec->header.sh_addr;
2617 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2618 }
2619
2620 sec = obj_find_section(f, ".text.init");
2621 if (sec) {
2622 module->runsize = sec->header.sh_addr - m_addr;
2623 }
2624 sec = obj_find_section(f, ".data.init");
2625 if (sec) {
2626 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002627 module->runsize > sec->header.sh_addr - m_addr)
2628 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002629 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002630 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2631 if (sec && sec->header.sh_size) {
2632 module->archdata_start = (void*)sec->header.sh_addr;
2633 module->archdata_end = module->archdata_start + sec->header.sh_size;
2634 }
2635 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2636 if (sec && sec->header.sh_size) {
2637 module->kallsyms_start = (void*)sec->header.sh_addr;
2638 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2639 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002640
Eric Andersen9f16d612000-06-12 23:11:16 +00002641 /* Whew! All of the initialization is complete. Collect the final
2642 module image and give it to the kernel. */
2643
2644 image = xmalloc(m_size);
2645 obj_create_image(f, image);
2646
Eric Andersencb3b9b12004-06-22 11:50:52 +00002647 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002648 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002649 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002650
2651 free(image);
2652
2653 return ret == 0;
2654}
2655
Eric Andersen9f16d612000-06-12 23:11:16 +00002656
2657/*======================================================================*/
2658
Eric Andersen044228d2001-07-17 01:12:36 +00002659static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002660obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2661 const char *string)
2662{
2663 struct obj_string_patch *p;
2664 struct obj_section *strsec;
2665 size_t len = strlen(string) + 1;
2666 char *loc;
2667
2668 p = xmalloc(sizeof(*p));
2669 p->next = f->string_patches;
2670 p->reloc_secidx = secidx;
2671 p->reloc_offset = offset;
2672 f->string_patches = p;
2673
2674 strsec = obj_find_section(f, ".kstrtab");
2675 if (strsec == NULL) {
2676 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2677 p->string_offset = 0;
2678 loc = strsec->contents;
2679 } else {
2680 p->string_offset = strsec->header.sh_size;
2681 loc = obj_extend_section(strsec, len);
2682 }
2683 memcpy(loc, string, len);
2684
2685 return 1;
2686}
2687
Eric Andersen044228d2001-07-17 01:12:36 +00002688static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002689obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2690 struct obj_symbol *sym)
2691{
2692 struct obj_symbol_patch *p;
2693
2694 p = xmalloc(sizeof(*p));
2695 p->next = f->symbol_patches;
2696 p->reloc_secidx = secidx;
2697 p->reloc_offset = offset;
2698 p->sym = sym;
2699 f->symbol_patches = p;
2700
2701 return 1;
2702}
2703
Eric Andersen044228d2001-07-17 01:12:36 +00002704static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002705{
2706 unsigned long i;
2707 int ret = 1;
2708
2709 for (i = 0; i < HASH_BUCKETS; ++i) {
2710 struct obj_symbol *sym;
2711 for (sym = f->symtab[i]; sym; sym = sym->next)
2712 if (sym->secidx == SHN_UNDEF) {
2713 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2714 sym->secidx = SHN_ABS;
2715 sym->value = 0;
2716 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002717 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002718 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00002719 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002720 ret = 0;
2721 }
2722 }
2723 }
2724
2725 return ret;
2726}
2727
Eric Andersen044228d2001-07-17 01:12:36 +00002728static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002729{
2730 struct common_entry {
2731 struct common_entry *next;
2732 struct obj_symbol *sym;
2733 } *common_head = NULL;
2734
2735 unsigned long i;
2736
2737 for (i = 0; i < HASH_BUCKETS; ++i) {
2738 struct obj_symbol *sym;
2739 for (sym = f->symtab[i]; sym; sym = sym->next)
2740 if (sym->secidx == SHN_COMMON) {
2741 /* Collect all COMMON symbols and sort them by size so as to
2742 minimize space wasted by alignment requirements. */
2743 {
2744 struct common_entry **p, *n;
2745 for (p = &common_head; *p; p = &(*p)->next)
2746 if (sym->size <= (*p)->sym->size)
2747 break;
2748
2749 n = alloca(sizeof(*n));
2750 n->next = *p;
2751 n->sym = sym;
2752 *p = n;
2753 }
2754 }
2755 }
2756
2757 for (i = 1; i < f->local_symtab_size; ++i) {
2758 struct obj_symbol *sym = f->local_symtab[i];
2759 if (sym && sym->secidx == SHN_COMMON) {
2760 struct common_entry **p, *n;
2761 for (p = &common_head; *p; p = &(*p)->next)
2762 if (sym == (*p)->sym)
2763 break;
2764 else if (sym->size < (*p)->sym->size) {
2765 n = alloca(sizeof(*n));
2766 n->next = *p;
2767 n->sym = sym;
2768 *p = n;
2769 break;
2770 }
2771 }
2772 }
2773
2774 if (common_head) {
2775 /* Find the bss section. */
2776 for (i = 0; i < f->header.e_shnum; ++i)
2777 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2778 break;
2779
2780 /* If for some reason there hadn't been one, create one. */
2781 if (i == f->header.e_shnum) {
2782 struct obj_section *sec;
2783
2784 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2785 f->sections[i] = sec = arch_new_section();
2786 f->header.e_shnum = i + 1;
2787
2788 memset(sec, 0, sizeof(*sec));
2789 sec->header.sh_type = SHT_PROGBITS;
2790 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2791 sec->name = ".bss";
2792 sec->idx = i;
2793 }
2794
2795 /* Allocate the COMMONS. */
2796 {
2797 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2798 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2799 struct common_entry *c;
2800
2801 for (c = common_head; c; c = c->next) {
2802 ElfW(Addr) align = c->sym->value;
2803
2804 if (align > max_align)
2805 max_align = align;
2806 if (bss_size & (align - 1))
2807 bss_size = (bss_size | (align - 1)) + 1;
2808
2809 c->sym->secidx = i;
2810 c->sym->value = bss_size;
2811
2812 bss_size += c->sym->size;
2813 }
2814
2815 f->sections[i]->header.sh_size = bss_size;
2816 f->sections[i]->header.sh_addralign = max_align;
2817 }
2818 }
2819
2820 /* For the sake of patch relocation and parameter initialization,
2821 allocate zeroed data for NOBITS sections now. Note that after
2822 this we cannot assume NOBITS are really empty. */
2823 for (i = 0; i < f->header.e_shnum; ++i) {
2824 struct obj_section *s = f->sections[i];
2825 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002826 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002827 s->contents = memset(xmalloc(s->header.sh_size),
2828 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002829 else
2830 s->contents = NULL;
2831
Eric Andersen9f16d612000-06-12 23:11:16 +00002832 s->header.sh_type = SHT_PROGBITS;
2833 }
2834 }
2835}
2836
Eric Andersen044228d2001-07-17 01:12:36 +00002837static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002838{
2839 unsigned long dot = 0;
2840 struct obj_section *sec;
2841
2842 /* Finalize the positions of the sections relative to one another. */
2843
2844 for (sec = f->load_order; sec; sec = sec->load_next) {
2845 ElfW(Addr) align;
2846
2847 align = sec->header.sh_addralign;
2848 if (align && (dot & (align - 1)))
2849 dot = (dot | (align - 1)) + 1;
2850
2851 sec->header.sh_addr = dot;
2852 dot += sec->header.sh_size;
2853 }
2854
2855 return dot;
2856}
2857
Eric Andersen044228d2001-07-17 01:12:36 +00002858static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002859{
2860 int i, n = f->header.e_shnum;
2861 int ret = 1;
2862
2863 /* Finalize the addresses of the sections. */
2864
2865 f->baseaddr = base;
2866 for (i = 0; i < n; ++i)
2867 f->sections[i]->header.sh_addr += base;
2868
2869 /* And iterate over all of the relocations. */
2870
2871 for (i = 0; i < n; ++i) {
2872 struct obj_section *relsec, *symsec, *targsec, *strsec;
2873 ElfW(RelM) * rel, *relend;
2874 ElfW(Sym) * symtab;
2875 const char *strtab;
2876
2877 relsec = f->sections[i];
2878 if (relsec->header.sh_type != SHT_RELM)
2879 continue;
2880
2881 symsec = f->sections[relsec->header.sh_link];
2882 targsec = f->sections[relsec->header.sh_info];
2883 strsec = f->sections[symsec->header.sh_link];
2884
2885 rel = (ElfW(RelM) *) relsec->contents;
2886 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2887 symtab = (ElfW(Sym) *) symsec->contents;
2888 strtab = (const char *) strsec->contents;
2889
2890 for (; rel < relend; ++rel) {
2891 ElfW(Addr) value = 0;
2892 struct obj_symbol *intsym = NULL;
2893 unsigned long symndx;
2894 ElfW(Sym) * extsym = 0;
2895 const char *errmsg;
2896
2897 /* Attempt to find a value to use for this relocation. */
2898
2899 symndx = ELFW(R_SYM) (rel->r_info);
2900 if (symndx) {
2901 /* Note we've already checked for undefined symbols. */
2902
2903 extsym = &symtab[symndx];
2904 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2905 /* Local symbols we look up in the local table to be sure
2906 we get the one that is really intended. */
2907 intsym = f->local_symtab[symndx];
2908 } else {
2909 /* Others we look up in the hash table. */
2910 const char *name;
2911 if (extsym->st_name)
2912 name = strtab + extsym->st_name;
2913 else
2914 name = f->sections[extsym->st_shndx]->name;
2915 intsym = obj_find_symbol(f, name);
2916 }
2917
2918 value = obj_symbol_final_value(f, intsym);
2919 intsym->referenced = 1;
2920 }
2921#if SHT_RELM == SHT_RELA
2922#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2923 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2924 if (!extsym || !extsym->st_name ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002925 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00002926#endif
2927 value += rel->r_addend;
2928#endif
2929
2930 /* Do it! */
2931 switch (arch_apply_relocation
2932 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002933 case obj_reloc_ok:
2934 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002935
Eric Andersen3b1a7442003-12-24 20:30:45 +00002936 case obj_reloc_overflow:
2937 errmsg = "Relocation overflow";
2938 goto bad_reloc;
2939 case obj_reloc_dangerous:
2940 errmsg = "Dangerous relocation";
2941 goto bad_reloc;
2942 case obj_reloc_unhandled:
2943 errmsg = "Unhandled relocation";
2944bad_reloc:
2945 if (extsym) {
2946 bb_error_msg("%s of type %ld for %s", errmsg,
2947 (long) ELFW(R_TYPE) (rel->r_info),
2948 strtab + extsym->st_name);
2949 } else {
2950 bb_error_msg("%s of type %ld", errmsg,
2951 (long) ELFW(R_TYPE) (rel->r_info));
2952 }
2953 ret = 0;
2954 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002955 }
2956 }
2957 }
2958
2959 /* Finally, take care of the patches. */
2960
2961 if (f->string_patches) {
2962 struct obj_string_patch *p;
2963 struct obj_section *strsec;
2964 ElfW(Addr) strsec_base;
2965 strsec = obj_find_section(f, ".kstrtab");
2966 strsec_base = strsec->header.sh_addr;
2967
2968 for (p = f->string_patches; p; p = p->next) {
2969 struct obj_section *targsec = f->sections[p->reloc_secidx];
2970 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2971 = strsec_base + p->string_offset;
2972 }
2973 }
2974
2975 if (f->symbol_patches) {
2976 struct obj_symbol_patch *p;
2977
2978 for (p = f->symbol_patches; p; p = p->next) {
2979 struct obj_section *targsec = f->sections[p->reloc_secidx];
2980 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2981 = obj_symbol_final_value(f, p->sym);
2982 }
2983 }
2984
2985 return ret;
2986}
2987
Eric Andersen044228d2001-07-17 01:12:36 +00002988static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002989{
2990 struct obj_section *sec;
2991 ElfW(Addr) base = f->baseaddr;
2992
2993 for (sec = f->load_order; sec; sec = sec->load_next) {
2994 char *secimg;
2995
Eric Andersen2bf658d2001-02-24 20:01:53 +00002996 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002997 continue;
2998
2999 secimg = image + (sec->header.sh_addr - base);
3000
3001 /* Note that we allocated data for NOBITS sections earlier. */
3002 memcpy(secimg, sec->contents, sec->header.sh_size);
3003 }
3004
3005 return 1;
3006}
3007
3008/*======================================================================*/
3009
Eric Andersen044228d2001-07-17 01:12:36 +00003010static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003011{
3012 struct obj_file *f;
3013 ElfW(Shdr) * section_headers;
3014 int shnum, i;
3015 char *shstrtab;
3016
3017 /* Read the file header. */
3018
3019 f = arch_new_file();
3020 memset(f, 0, sizeof(*f));
3021 f->symbol_cmp = strcmp;
3022 f->symbol_hash = obj_elf_hash;
3023 f->load_order_search_start = &f->load_order;
3024
3025 fseek(fp, 0, SEEK_SET);
3026 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003027 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003028 return NULL;
3029 }
3030
3031 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003032 || f->header.e_ident[EI_MAG1] != ELFMAG1
3033 || f->header.e_ident[EI_MAG2] != ELFMAG2
3034 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003035 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003036 return NULL;
3037 }
3038 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003039 || f->header.e_ident[EI_DATA] != ELFDATAM
3040 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3041 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003042 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003043 return NULL;
3044 }
3045 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003046 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003047 return NULL;
3048 }
3049
3050 /* Read the section headers. */
3051
3052 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003053 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003054 (unsigned long) f->header.e_shentsize,
3055 (unsigned long) sizeof(ElfW(Shdr)));
3056 return NULL;
3057 }
3058
3059 shnum = f->header.e_shnum;
3060 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3061 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3062
3063 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3064 fseek(fp, f->header.e_shoff, SEEK_SET);
3065 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003066 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003067 return NULL;
3068 }
3069
3070 /* Read the section data. */
3071
3072 for (i = 0; i < shnum; ++i) {
3073 struct obj_section *sec;
3074
3075 f->sections[i] = sec = arch_new_section();
3076 memset(sec, 0, sizeof(*sec));
3077
3078 sec->header = section_headers[i];
3079 sec->idx = i;
3080
Eric Andersen2bf658d2001-02-24 20:01:53 +00003081 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003082 case SHT_NULL:
3083 case SHT_NOTE:
3084 case SHT_NOBITS:
3085 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003086 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003087
3088 case SHT_PROGBITS:
3089#if LOADBITS
3090 if (!loadprogbits) {
3091 sec->contents = NULL;
3092 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003093 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003094#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003095 case SHT_SYMTAB:
3096 case SHT_STRTAB:
3097 case SHT_RELM:
3098 if (sec->header.sh_size > 0) {
3099 sec->contents = xmalloc(sec->header.sh_size);
3100 fseek(fp, sec->header.sh_offset, SEEK_SET);
3101 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3102 bb_perror_msg("error reading ELF section data");
3103 return NULL;
3104 }
3105 } else {
3106 sec->contents = NULL;
3107 }
3108 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003109
3110#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003111 case SHT_RELA:
3112 bb_error_msg("RELA relocations not supported on this architecture");
3113 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003114#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003115 case SHT_REL:
3116 bb_error_msg("REL relocations not supported on this architecture");
3117 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003118#endif
3119
Eric Andersen3b1a7442003-12-24 20:30:45 +00003120 default:
3121 if (sec->header.sh_type >= SHT_LOPROC) {
3122 /* Assume processor specific section types are debug
3123 info and can safely be ignored. If this is ever not
3124 the case (Hello MIPS?), don't put ifdefs here but
3125 create an arch_load_proc_section(). */
3126 break;
3127 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003128
Eric Andersen3b1a7442003-12-24 20:30:45 +00003129 bb_error_msg("can't handle sections of type %ld",
3130 (long) sec->header.sh_type);
3131 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 }
3133 }
3134
3135 /* Do what sort of interpretation as needed by each section. */
3136
3137 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3138
3139 for (i = 0; i < shnum; ++i) {
3140 struct obj_section *sec = f->sections[i];
3141 sec->name = shstrtab + sec->header.sh_name;
3142 }
3143
3144 for (i = 0; i < shnum; ++i) {
3145 struct obj_section *sec = f->sections[i];
3146
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003147 /* .modinfo should be contents only but gcc has no attribute for that.
3148 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3149 */
3150 if (strcmp(sec->name, ".modinfo") == 0)
3151 sec->header.sh_flags &= ~SHF_ALLOC;
3152
Eric Andersen9f16d612000-06-12 23:11:16 +00003153 if (sec->header.sh_flags & SHF_ALLOC)
3154 obj_insert_section_load_order(f, sec);
3155
3156 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003157 case SHT_SYMTAB:
3158 {
3159 unsigned long nsym, j;
3160 char *strtab;
3161 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003162
Eric Andersen3b1a7442003-12-24 20:30:45 +00003163 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3164 bb_error_msg("symbol size mismatch: %lu != %lu",
3165 (unsigned long) sec->header.sh_entsize,
3166 (unsigned long) sizeof(ElfW(Sym)));
3167 return NULL;
3168 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003169
Eric Andersen3b1a7442003-12-24 20:30:45 +00003170 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3171 strtab = f->sections[sec->header.sh_link]->contents;
3172 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003173
Eric Andersen3b1a7442003-12-24 20:30:45 +00003174 /* Allocate space for a table of local symbols. */
3175 j = f->local_symtab_size = sec->header.sh_info;
3176 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003177
Eric Andersen3b1a7442003-12-24 20:30:45 +00003178 /* Insert all symbols into the hash table. */
3179 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3180 ElfW(Addr) val = sym->st_value;
3181 const char *name;
3182 if (sym->st_name)
3183 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003184 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003185 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003186 else
3187 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003188
Eric Andersenbf833552003-08-13 19:56:33 +00003189#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003190 /*
3191 * For sh64 it is possible that the target of a branch
3192 * requires a mode switch (32 to 16 and back again).
3193 *
3194 * This is implied by the lsb being set in the target
3195 * address for SHmedia mode and clear for SHcompact.
3196 */
3197 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003198#endif
3199
Eric Andersen3b1a7442003-12-24 20:30:45 +00003200 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3201 val, sym->st_size);
3202 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003203 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003204 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003205
Eric Andersen3b1a7442003-12-24 20:30:45 +00003206 case SHT_RELM:
3207 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3208 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3209 (unsigned long) sec->header.sh_entsize,
3210 (unsigned long) sizeof(ElfW(RelM)));
3211 return NULL;
3212 }
3213 break;
3214 /* XXX Relocation code from modutils-2.3.19 is not here.
3215 * Why? That's about 20 lines of code from obj/obj_load.c,
3216 * which gets done in a second pass through the sections.
3217 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003218 }
3219 }
3220
3221 return f;
3222}
3223
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003224#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003225/*
3226 * load the unloaded sections directly into the memory allocated by
3227 * kernel for the module
3228 */
3229
Eric Andersenac5dbd12001-08-22 05:26:08 +00003230static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003231{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003232 ElfW(Addr) base = f->baseaddr;
3233 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003234
Eric Andersen8ae319a2001-05-21 16:09:18 +00003235 for (sec = f->load_order; sec; sec = sec->load_next) {
3236
3237 /* section already loaded? */
3238 if (sec->contents != NULL)
3239 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003240
Eric Andersen8ae319a2001-05-21 16:09:18 +00003241 if (sec->header.sh_size == 0)
3242 continue;
3243
3244 sec->contents = imagebase + (sec->header.sh_addr - base);
3245 fseek(fp, sec->header.sh_offset, SEEK_SET);
3246 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003247 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003248 return 0;
3249 }
3250
3251 }
3252 return 1;
3253}
3254#endif
3255
Eric Andersen9f16d612000-06-12 23:11:16 +00003256static void hide_special_symbols(struct obj_file *f)
3257{
3258 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003259 SPFX "cleanup_module",
3260 SPFX "init_module",
3261 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003262 NULL
3263 };
3264
3265 struct obj_symbol *sym;
3266 const char *const *p;
3267
3268 for (p = specials; *p; ++p)
3269 if ((sym = obj_find_symbol(f, *p)) != NULL)
3270 sym->info =
3271 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3272}
3273
Glenn L McGrath759515c2003-08-30 06:00:33 +00003274
Eric Andersen71ae64b2002-10-10 04:20:21 +00003275#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003276static int obj_gpl_license(struct obj_file *f, const char **license)
3277{
3278 struct obj_section *sec;
3279 /* This list must match *exactly* the list of allowable licenses in
3280 * linux/include/linux/module.h. Checking for leading "GPL" will not
3281 * work, somebody will use "GPL sucks, this is proprietary".
3282 */
3283 static const char *gpl_licenses[] = {
3284 "GPL",
3285 "GPL v2",
3286 "GPL and additional rights",
3287 "Dual BSD/GPL",
3288 "Dual MPL/GPL",
3289 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003290
Eric Andersen166fa462002-09-16 05:30:24 +00003291 if ((sec = obj_find_section(f, ".modinfo"))) {
3292 const char *value, *ptr, *endptr;
3293 ptr = sec->contents;
3294 endptr = ptr + sec->header.sh_size;
3295 while (ptr < endptr) {
3296 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3297 int i;
3298 if (license)
3299 *license = value+1;
3300 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3301 if (strcmp(value+1, gpl_licenses[i]) == 0)
3302 return(0);
3303 }
3304 return(2);
3305 }
3306 if (strchr(ptr, '\0'))
3307 ptr = strchr(ptr, '\0') + 1;
3308 else
3309 ptr = endptr;
3310 }
3311 }
3312 return(1);
3313}
3314
3315#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3316#define TAINT_PROPRIETORY_MODULE (1<<0)
3317#define TAINT_FORCED_MODULE (1<<1)
3318#define TAINT_UNSAFE_SMP (1<<2)
3319#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3320
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003321static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003322 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3323{
3324 char buf[80];
3325 int oldval;
3326 static int first = 1;
3327 if (fd < 0 && !kernel_has_tainted)
3328 return; /* New modutils on old kernel */
3329 printf("Warning: loading %s will taint the kernel: %s%s\n",
3330 m_name, text1, text2);
3331 if (first) {
3332 printf(" See %s for information about tainted modules\n", TAINT_URL);
3333 first = 0;
3334 }
3335 if (fd >= 0) {
3336 read(fd, buf, sizeof(buf)-1);
3337 buf[sizeof(buf)-1] = '\0';
3338 oldval = strtoul(buf, NULL, 10);
3339 sprintf(buf, "%d\n", oldval | taint);
3340 write(fd, buf, strlen(buf));
3341 }
3342}
3343
3344/* Check if loading this module will taint the kernel. */
3345static void check_tainted_module(struct obj_file *f, char *m_name)
3346{
3347 static const char tainted_file[] = TAINT_FILENAME;
3348 int fd, kernel_has_tainted;
3349 const char *ptr;
3350
3351 kernel_has_tainted = 1;
3352 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3353 if (errno == ENOENT)
3354 kernel_has_tainted = 0;
3355 else if (errno == EACCES)
3356 kernel_has_tainted = 1;
3357 else {
3358 perror(tainted_file);
3359 kernel_has_tainted = 0;
3360 }
3361 }
3362
3363 switch (obj_gpl_license(f, &ptr)) {
3364 case 0:
3365 break;
3366 case 1:
3367 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3368 break;
3369 case 2:
3370 /* The module has a non-GPL license so we pretend that the
3371 * kernel always has a taint flag to get a warning even on
3372 * kernels without the proc flag.
3373 */
3374 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3375 break;
3376 default:
3377 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3378 break;
3379 }
3380
3381 if (flag_force_load)
3382 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3383
3384 if (fd >= 0)
3385 close(fd);
3386}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003387#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3388#define check_tainted_module(x, y) do { } while(0);
3389#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003390
Eric Andersen889dd202003-01-23 04:48:34 +00003391#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3392/* add module source, timestamp, kernel version and a symbol for the
3393 * start of some sections. this info is used by ksymoops to do better
3394 * debugging.
3395 */
3396static int
3397get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3398{
3399#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003400 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003401#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003402 strncpy(str, "???", sizeof(str));
3403 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003404#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3405}
3406
3407/* add module source, timestamp, kernel version and a symbol for the
3408 * start of some sections. this info is used by ksymoops to do better
3409 * debugging.
3410 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003411static void
Eric Andersen889dd202003-01-23 04:48:34 +00003412add_ksymoops_symbols(struct obj_file *f, const char *filename,
3413 const char *m_name)
3414{
3415 static const char symprefix[] = "__insmod_";
3416 struct obj_section *sec;
3417 struct obj_symbol *sym;
3418 char *name, *absolute_filename;
3419 char str[STRVERSIONLEN], real[PATH_MAX];
3420 int i, l, lm_name, lfilename, use_ksymtab, version;
3421 struct stat statbuf;
3422
3423 static const char *section_names[] = {
3424 ".text",
3425 ".rodata",
3426 ".data",
3427 ".bss"
Eric Andersen3b1a7442003-12-24 20:30:45 +00003428 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003429 };
3430
3431 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003432 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003433 }
3434 else {
3435 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003436 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003437 errno = save_errno;
3438 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003439 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003440 }
3441
3442 lm_name = strlen(m_name);
3443 lfilename = strlen(absolute_filename);
3444
3445 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3446 * are not to be exported. otherwise leave ksymtab alone for now, the
3447 * "export all symbols" compatibility code will export these symbols later.
3448 */
3449 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3450
3451 if ((sec = obj_find_section(f, ".this"))) {
3452 /* tag the module header with the object name, last modified
3453 * timestamp and module version. worst case for module version
3454 * is 0xffffff, decimal 16777215. putting all three fields in
3455 * one symbol is less readable but saves kernel space.
3456 */
3457 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003458 lm_name+ /* module name */
3459 2+ /* "_O" */
3460 lfilename+ /* object filename */
3461 2+ /* "_M" */
3462 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3463 2+ /* "_V" */
3464 8+ /* version in dec */
3465 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003466 name = xmalloc(l);
3467 if (stat(absolute_filename, &statbuf) != 0)
3468 statbuf.st_mtime = 0;
3469 version = get_module_version(f, str); /* -1 if not found */
3470 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003471 symprefix, m_name, absolute_filename,
3472 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3473 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003474 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003475 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3476 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003477 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003478 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003479 }
3480 free(absolute_filename);
3481#ifdef _NOT_SUPPORTED_
3482 /* record where the persistent data is going, same address as previous symbol */
3483
3484 if (f->persist) {
3485 l = sizeof(symprefix)+ /* "__insmod_" */
3486 lm_name+ /* module name */
3487 2+ /* "_P" */
3488 strlen(f->persist)+ /* data store */
3489 1; /* nul */
3490 name = xmalloc(l);
3491 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003492 symprefix, m_name, f->persist);
Eric Andersen889dd202003-01-23 04:48:34 +00003493 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003494 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003495 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003496 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003497 }
3498#endif /* _NOT_SUPPORTED_ */
3499 /* tag the desired sections if size is non-zero */
3500
3501 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3502 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003503 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003504 l = sizeof(symprefix)+ /* "__insmod_" */
3505 lm_name+ /* module name */
3506 2+ /* "_S" */
3507 strlen(sec->name)+ /* section name */
3508 2+ /* "_L" */
3509 8+ /* length in dec */
3510 1; /* nul */
3511 name = xmalloc(l);
3512 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003513 symprefix, m_name, sec->name,
3514 (long)sec->header.sh_size);
Eric Andersen889dd202003-01-23 04:48:34 +00003515 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003516 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003517 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003518 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003519 }
3520 }
3521}
3522#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3523
Eric Andersenbe65c352003-01-23 04:57:35 +00003524#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3525static void print_load_map(struct obj_file *f)
3526{
3527 struct obj_symbol *sym;
3528 struct obj_symbol **all, **p;
3529 struct obj_section *sec;
3530 int i, nsyms, *loaded;
3531
3532 /* Report on the section layout. */
3533
3534 printf("Sections: Size %-*s Align\n",
3535 (int) (2 * sizeof(void *)), "Address");
3536
3537 for (sec = f->load_order; sec; sec = sec->load_next) {
3538 int a;
3539 unsigned long tmp;
3540
3541 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3542 tmp >>= 1;
3543 if (a == -1)
3544 a = 0;
3545
3546 printf("%-15s %08lx %0*lx 2**%d\n",
3547 sec->name,
3548 (long)sec->header.sh_size,
3549 (int) (2 * sizeof(void *)),
3550 (long)sec->header.sh_addr,
3551 a);
3552 }
3553#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3554 /* Quick reference which section indicies are loaded. */
3555
3556 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3557 while (--i >= 0)
3558 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3559
3560 /* Collect the symbols we'll be listing. */
3561
3562 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3563 for (sym = f->symtab[i]; sym; sym = sym->next)
3564 if (sym->secidx <= SHN_HIRESERVE
3565 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3566 ++nsyms;
3567
3568 all = alloca(nsyms * sizeof(struct obj_symbol *));
3569
3570 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3571 for (sym = f->symtab[i]; sym; sym = sym->next)
3572 if (sym->secidx <= SHN_HIRESERVE
3573 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3574 *p++ = sym;
3575
3576 /* And list them. */
3577 printf("\nSymbols:\n");
3578 for (p = all; p < all + nsyms; ++p) {
3579 char type = '?';
3580 unsigned long value;
3581
3582 sym = *p;
3583 if (sym->secidx == SHN_ABS) {
3584 type = 'A';
3585 value = sym->value;
3586 } else if (sym->secidx == SHN_UNDEF) {
3587 type = 'U';
3588 value = 0;
3589 } else {
3590 sec = f->sections[sym->secidx];
3591
3592 if (sec->header.sh_type == SHT_NOBITS)
3593 type = 'B';
3594 else if (sec->header.sh_flags & SHF_ALLOC) {
3595 if (sec->header.sh_flags & SHF_EXECINSTR)
3596 type = 'T';
3597 else if (sec->header.sh_flags & SHF_WRITE)
3598 type = 'D';
3599 else
3600 type = 'R';
3601 }
3602 value = sym->value + sec->header.sh_addr;
3603 }
3604
3605 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
3606 type = tolower(type);
3607
3608 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3609 type, sym->name);
3610 }
3611#endif
3612}
3613
3614#endif
3615
Eric Andersen9f16d612000-06-12 23:11:16 +00003616extern int insmod_main( int argc, char **argv)
3617{
Eric Andersena18aaf12001-01-24 19:07:09 +00003618 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003619 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003620 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003621 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003622 unsigned long m_size;
3623 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003624 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003625 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003626 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003627 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003628 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003629#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003630 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003631 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003632 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003633#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003634#ifdef CONFIG_FEATURE_CLEAN_UP
3635 FILE *fp = 0;
3636#else
3637 FILE *fp;
3638#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003639#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3640 int flag_print_load_map = 0;
3641#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003642 int k_version = 0;
3643 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003644
Erik Andersene49d5ec2000-02-08 19:58:47 +00003645 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003646#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003647 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003648#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003649 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003650#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003651 {
3652 switch (opt) {
3653 case 'f': /* force loading */
3654 flag_force_load = 1;
3655 break;
3656 case 'k': /* module loaded by kerneld, auto-cleanable */
3657 flag_autoclean = 1;
3658 break;
3659 case 's': /* log to syslog */
3660 /* log to syslog -- not supported */
3661 /* but kernel needs this for request_module(), */
3662 /* as this calls: modprobe -k -s -- <module> */
3663 /* so silently ignore this flag */
3664 break;
3665 case 'v': /* verbose output */
3666 flag_verbose = 1;
3667 break;
3668 case 'q': /* silent */
3669 flag_quiet = 1;
3670 break;
3671 case 'x': /* do not export externs */
3672 flag_export = 0;
3673 break;
3674 case 'o': /* name the output module */
3675 free(m_name);
3676 m_name = bb_xstrdup(optarg);
3677 break;
3678 case 'L': /* Stub warning */
3679 /* This is needed for compatibility with modprobe.
3680 * In theory, this does locking, but we don't do
3681 * that. So be careful and plan your life around not
3682 * loading the same module 50 times concurrently. */
3683 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003684#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003685 case 'm': /* print module load map */
3686 flag_print_load_map = 1;
3687 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003688#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003689 default:
3690 bb_show_usage();
3691 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003692 }
Eric Andersen03d80912003-12-19 21:04:19 +00003693
Eric Andersena18aaf12001-01-24 19:07:09 +00003694 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003695 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003696 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003697
Erik Andersene49d5ec2000-02-08 19:58:47 +00003698 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003699 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003700 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003701 len = strlen(tmp);
3702
Eric Andersen03d80912003-12-19 21:04:19 +00003703 if (uname(&myuname) == 0) {
3704 if (myuname.release[0] == '2') {
3705 k_version = myuname.release[2] - '0';
3706 }
3707 }
3708
3709#if defined(CONFIG_FEATURE_2_6_MODULES)
3710 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003711 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00003712 len-=3;
3713 tmp[len] = '\0';
3714 }
3715 else
3716#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003717 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3718 len-=2;
3719 tmp[len] = '\0';
3720 }
Eric Andersen2d342152002-06-18 05:16:25 +00003721
Eric Andersen03d80912003-12-19 21:04:19 +00003722
3723#if defined(CONFIG_FEATURE_2_6_MODULES)
3724 if (k_version > 4)
3725 bb_xasprintf(&m_fullName, "%s.ko", tmp);
3726 else
Eric Andersen03d80912003-12-19 21:04:19 +00003727#endif
Eric Andersen66e21fd2004-01-05 23:49:37 +00003728 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003729
Eric Andersen61f83052002-06-22 17:15:42 +00003730 if (!m_name) {
3731 m_name = tmp;
3732 } else {
3733 free(tmp1);
3734 tmp1 = 0; /* flag for free(m_name) before exit() */
3735 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003736
Eric Andersen14d35432001-05-14 17:07:32 +00003737 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003738 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3739 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003740 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3741 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003742 if (k_version) { /* uname succeedd */
3743 char *module_dir;
3744 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003745 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003746
Eric Andersen03d80912003-12-19 21:04:19 +00003747 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003748 /* Jump through hoops in case /lib/modules/`uname -r`
3749 * is a symlink. We do not want recursive_action to
3750 * follow symlinks, but we do want to follow the
3751 * /lib/modules/`uname -r` dir, So resolve it ourselves
3752 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00003753 if (realpath (tmdn, real_module_dir) == NULL)
3754 module_dir = tmdn;
3755 else
3756 module_dir = real_module_dir;
3757 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003758 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00003759 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00003760 }
3761
3762 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00003763 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003764 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003765 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003766
Eric Andersen03d80912003-12-19 21:04:19 +00003767 free(m_filename);
3768 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003769 if (realpath (_PATH_MODULES, module_dir) == NULL)
3770 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003771 /* No module found under /lib/modules/`uname -r`, this
3772 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00003773 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00003774 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00003775 {
Eric Andersen61f83052002-06-22 17:15:42 +00003776 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00003777 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00003778 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003779 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00003780 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00003781 }
3782 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003783 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00003784 }
Eric Andersen03d80912003-12-19 21:04:19 +00003785 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00003786 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00003787
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00003788 if (!flag_quiet)
3789 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003790
Eric Andersene7047882003-12-11 01:42:13 +00003791#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003792 if (k_version > 4)
3793 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003794 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00003795 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003796 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00003797 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00003798#endif
3799
Eric Andersen8ae319a2001-05-21 16:09:18 +00003800 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003801 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003802
Eric Andersen9f16d612000-06-12 23:11:16 +00003803 if (get_modinfo_value(f, "kernel_version") == NULL)
3804 m_has_modinfo = 0;
3805 else
3806 m_has_modinfo = 1;
3807
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003808#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003809 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00003810 if (!flag_quiet) {
3811 if (uname(&uts_info) < 0)
3812 uts_info.release[0] = '\0';
3813 if (m_has_modinfo) {
3814 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00003815 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003816 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00003817 "compiled for");
3818 goto out;
3819 }
3820 }
3821
3822 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
3823 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003824 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003825 "\t%s was compiled for kernel version %s\n"
3826 "\twhile this kernel is version %s",
3827 m_filename, m_strversion, uts_info.release);
3828 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003829 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00003830 "\t%s was compiled for kernel version %s\n"
3831 "\twhile this kernel is version %s.",
3832 m_filename, m_strversion, uts_info.release);
3833 goto out;
3834 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003835 }
3836 }
3837 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003838#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003839
Eric Andersencb3b9b12004-06-22 11:50:52 +00003840 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003841 if (!new_get_kernel_symbols())
3842 goto out;
3843 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00003844 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003845 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003846 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00003847 }
3848
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003849#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003850 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00003851 if (m_has_modinfo)
3852 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003853
3854 if (m_crcs != k_crcs)
3855 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003856#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003857
Erik Andersene49d5ec2000-02-08 19:58:47 +00003858 /* Let the module know about the kernel symbols. */
3859 add_kernel_symbols(f);
3860
Eric Andersen9f16d612000-06-12 23:11:16 +00003861 /* Allocate common symbols, symbol tables, and string tables. */
3862
Eric Andersencb3b9b12004-06-22 11:50:52 +00003863 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003864 {
3865 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003866 }
3867
Eric Andersen9f16d612000-06-12 23:11:16 +00003868 if (!obj_check_undefineds(f)) {
3869 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003870 }
3871 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00003872 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003873
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003874 /* done with the module name, on to the optional var=value arguments */
3875 ++optind;
3876
Eric Andersen9f16d612000-06-12 23:11:16 +00003877 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00003878 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00003879 {
3880 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003881 }
3882 }
3883
Eric Andersen9f16d612000-06-12 23:11:16 +00003884 arch_create_got(f);
3885 hide_special_symbols(f);
3886
Eric Andersen889dd202003-01-23 04:48:34 +00003887#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3888 add_ksymoops_symbols(f, m_filename, m_name);
3889#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3890
Eric Andersencb3b9b12004-06-22 11:50:52 +00003891 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00003892
Erik Andersene49d5ec2000-02-08 19:58:47 +00003893 /* Find current size of the module */
3894 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003895
3896
Erik Andersene49d5ec2000-02-08 19:58:47 +00003897 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00003898 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003899 case EEXIST:
3900 bb_error_msg("A module named %s already exists", m_name);
3901 goto out;
3902 case ENOMEM:
3903 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
3904 m_size);
3905 goto out;
3906 default:
3907 bb_perror_msg("create_module: %s", m_name);
3908 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003909 }
Erik Andersend387d011999-12-21 02:55:11 +00003910
Eric Andersen8ae319a2001-05-21 16:09:18 +00003911#if !LOADBITS
3912 /*
3913 * the PROGBITS section was not loaded by the obj_load
3914 * now we can load them directly into the kernel memory
3915 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00003916 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00003917 delete_module(m_name);
3918 goto out;
3919 }
Eric Andersen03d80912003-12-19 21:04:19 +00003920#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00003921
Eric Andersen9f16d612000-06-12 23:11:16 +00003922 if (!obj_relocate(f, m_addr)) {
3923 delete_module(m_name);
3924 goto out;
3925 }
Erik Andersend387d011999-12-21 02:55:11 +00003926
Eric Andersencb3b9b12004-06-22 11:50:52 +00003927 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00003928 {
3929 delete_module(m_name);
3930 goto out;
3931 }
3932
Eric Andersenbe65c352003-01-23 04:57:35 +00003933#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3934 if(flag_print_load_map)
3935 print_load_map(f);
3936#endif
3937
Matt Kraai3e856ce2000-12-01 02:55:13 +00003938 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003939
3940out:
Eric Andersen61f83052002-06-22 17:15:42 +00003941#ifdef CONFIG_FEATURE_CLEAN_UP
3942 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003943 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00003944 if(tmp1) {
3945 free(tmp1);
3946 } else {
3947 free(m_name);
3948 }
3949 free(m_filename);
3950#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00003951 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003952}
Eric Andersene7047882003-12-11 01:42:13 +00003953
3954
3955#endif
3956
3957
3958#ifdef CONFIG_FEATURE_2_6_MODULES
3959
3960#include <sys/mman.h>
3961#include <asm/unistd.h>
3962#include <sys/syscall.h>
3963
3964/* We use error numbers in a loose translation... */
3965static const char *moderror(int err)
3966{
3967 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003968 case ENOEXEC:
3969 return "Invalid module format";
3970 case ENOENT:
3971 return "Unknown symbol in module";
3972 case ESRCH:
3973 return "Module has wrong symbol version";
3974 case EINVAL:
3975 return "Invalid parameters";
3976 default:
3977 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00003978 }
3979}
3980
3981extern int insmod_ng_main( int argc, char **argv)
3982{
3983 int i;
3984 int fd;
3985 long int ret;
3986 struct stat st;
3987 unsigned long len;
3988 void *map;
3989 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003990
Eric Andersene7047882003-12-11 01:42:13 +00003991 filename = argv[1];
3992 if (!filename) {
3993 bb_show_usage();
3994 return -1;
3995 }
3996
3997 /* Rest is options */
3998 for (i = 2; i < argc; i++) {
3999 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4000 /* Spaces handled by "" pairs, but no way of escaping quotes */
4001 if (strchr(argv[i], ' ')) {
4002 strcat(options, "\"");
4003 strcat(options, argv[i]);
4004 strcat(options, "\"");
4005 } else {
4006 strcat(options, argv[i]);
4007 }
4008 strcat(options, " ");
4009 }
4010
4011 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4012 bb_perror_msg_and_die("cannot open module `%s'", filename);
4013 }
4014
4015 fstat(fd, &st);
4016 len = st.st_size;
4017 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4018 if (map == MAP_FAILED) {
4019 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4020 }
4021
4022 ret = syscall(__NR_init_module, map, len, options);
4023 if (ret != 0) {
4024 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004025 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004026 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004027
Eric Andersene7047882003-12-11 01:42:13 +00004028 return 0;
4029}
4030
4031#endif