blob: a6afcecea2306945e1f483463ca8ece5ff3c086d [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 Andersenbf833552003-08-13 19:56:33 +00005 * This version of insmod supports x86, ARM, SH3/4/5, powerpc, m68k,
Miles Baderae28b042002-04-01 09:34:25 +00006 * MIPS, and v850e.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenbdfd0d72001-10-24 05:00:29 +00008 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
Eric Andersencb81e642003-07-14 21:21:08 +00009 * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +000010 * and Ron Alder <alder@lineo.com>
11 *
Miles Bader75ce8d72002-04-01 14:25:51 +000012 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000013 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000014 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000015 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
16 *
17 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
18 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
19 * very minor changes required to also work with StrongArm and presumably
20 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000021 *
Eric Andersenbf833552003-08-13 19:56:33 +000022 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
23 * Integrated support for sh64 (SH-5), from preliminary modutils
24 * patches from Benedict Gaster <benedict.gaster@superh.com>.
25 * Currently limited to support for 32bit ABI.
26 *
Eric Andersencffd5022002-05-24 06:50:15 +000027 * Magnus Damm <damm@opensource.se> 22-May-2002.
28 * The plt and got code are now using the same structs.
29 * Added generic linked list code to fully support PowerPC.
30 * Replaced the mess in arch_apply_relocation() with architecture blocks.
31 * The arch_create_got() function got cleaned up with architecture blocks.
32 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
33 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000034 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
35 * PowerPC specific code stolen from modutils-2.3.16,
36 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
37 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000038 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000040 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
41 * based on modutils-2.4.2
42 * MIPS specific support for Elf loading and relocation.
43 * Copyright 1996, 1997 Linux International.
44 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
45 *
Eric Andersen9f16d612000-06-12 23:11:16 +000046 * Based almost entirely on the Linux modutils-2.3.11 implementation.
47 * Copyright 1996, 1997 Linux International.
48 * New implementation contributed by Richard Henderson <rth@tamu.edu>
49 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
50 * Restructured (and partly rewritten) by:
51 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000052 *
53 * This program is free software; you can redistribute it and/or modify
54 * it under the terms of the GNU General Public License as published by
55 * the Free Software Foundation; either version 2 of the License, or
56 * (at your option) any later version.
57 *
58 * This program is distributed in the hope that it will be useful,
59 * but WITHOUT ANY WARRANTY; without even the implied warranty of
60 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
61 * General Public License for more details.
62 *
63 * You should have received a copy of the GNU General Public License
64 * along with this program; if not, write to the Free Software
65 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
66 *
67 */
68
Erik Andersen02104321999-12-17 18:57:34 +000069#include <stdlib.h>
70#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000071#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000072#include <errno.h>
73#include <unistd.h>
74#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000075#include <ctype.h>
76#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000077#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000078#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000079#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000080#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000081#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000082
Eric Andersenbdfd0d72001-10-24 05:00:29 +000083#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
84# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen64c8b172001-04-05 07:33:10 +000085# define new_sys_init_module init_module
86#else
87# define old_sys_init_module init_module
88#endif
89
Eric Andersenbdfd0d72001-10-24 05:00:29 +000090#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +000091#define LOADBITS 0
92#else
93#define LOADBITS 1
94#endif
95
Eric Andersen90fe7fe2001-02-20 20:47:08 +000096
97#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000098#define CONFIG_USE_PLT_ENTRIES
99#define CONFIG_PLT_ENTRY_SIZE 8
100#define CONFIG_USE_GOT_ENTRIES
101#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000102#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000103
Eric Andersencffd5022002-05-24 06:50:15 +0000104#define MATCH_MACHINE(x) (x == EM_ARM)
105#define SHT_RELM SHT_REL
106#define Elf32_RelM Elf32_Rel
107#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000108#endif
109
Eric Andersenbf77f612003-01-23 06:02:39 +0000110#if defined(__s390__)
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000111#define CONFIG_USE_PLT_ENTRIES
112#define CONFIG_PLT_ENTRY_SIZE 8
113#define CONFIG_USE_GOT_ENTRIES
114#define CONFIG_GOT_ENTRY_SIZE 8
115#define CONFIG_USE_SINGLE
Eric Andersenbf77f612003-01-23 06:02:39 +0000116
117#define MATCH_MACHINE(x) (x == EM_S390)
118#define SHT_RELM SHT_RELA
119#define Elf32_RelM Elf32_Rela
120#define ELFCLASSM ELFCLASS32
121#endif
122
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000123#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000124#define CONFIG_USE_GOT_ENTRIES
125#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000126#define CONFIG_USE_SINGLE
127
128#ifndef EM_486
129#define MATCH_MACHINE(x) (x == EM_386)
130#else
131#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
132#endif
133
134#define SHT_RELM SHT_REL
135#define Elf32_RelM Elf32_Rel
136#define ELFCLASSM ELFCLASS32
137#endif
138
139#if defined(__mc68000__)
140#define CONFIG_USE_GOT_ENTRIES
141#define CONFIG_GOT_ENTRY_SIZE 4
142#define CONFIG_USE_SINGLE
143
144#define MATCH_MACHINE(x) (x == EM_68K)
145#define SHT_RELM SHT_RELA
146#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000147#endif
148
Eric Andersen2bf658d2001-02-24 20:01:53 +0000149#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000150/* Account for ELF spec changes. */
151#ifndef EM_MIPS_RS3_LE
152#ifdef EM_MIPS_RS4_BE
153#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
154#else
155#define EM_MIPS_RS3_LE 10
156#endif
157#endif /* !EM_MIPS_RS3_LE */
158
159#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
160#define SHT_RELM SHT_REL
161#define Elf32_RelM Elf32_Rel
162#define ELFCLASSM ELFCLASS32
163#define ARCHDATAM "__dbe_table"
164#endif
165
166#if defined(__powerpc__)
167#define CONFIG_USE_PLT_ENTRIES
168#define CONFIG_PLT_ENTRY_SIZE 16
169#define CONFIG_USE_PLT_LIST
170#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
171#define CONFIG_USE_LIST
172
173#define MATCH_MACHINE(x) (x == EM_PPC)
174#define SHT_RELM SHT_RELA
175#define Elf32_RelM Elf32_Rela
176#define ELFCLASSM ELFCLASS32
177#define ARCHDATAM "__ftr_fixup"
178#endif
179
180#if defined(__sh__)
181#define CONFIG_USE_GOT_ENTRIES
182#define CONFIG_GOT_ENTRY_SIZE 4
183#define CONFIG_USE_SINGLE
184
185#define MATCH_MACHINE(x) (x == EM_SH)
186#define SHT_RELM SHT_RELA
187#define Elf32_RelM Elf32_Rela
188#define ELFCLASSM ELFCLASS32
189
Eric Andersenbf833552003-08-13 19:56:33 +0000190/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000191/* I'm not sure about big endian, so let's warn: */
192
Eric Andersenbf833552003-08-13 19:56:33 +0000193#if defined(__sh__) && defined(__BIG_ENDIAN__)
194#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000195#endif
196
197/* it may or may not work on the SH1/SH2... So let's error on those
198 also */
Eric Andersenbf833552003-08-13 19:56:33 +0000199#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && \
200 (defined(__sh__))
201#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000202#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000203#endif
204
Miles Baderae28b042002-04-01 09:34:25 +0000205#if defined (__v850e__)
206#define CONFIG_USE_PLT_ENTRIES
207#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000208#define CONFIG_USE_SINGLE
209
210#ifndef EM_CYGNUS_V850 /* grumble */
211#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000212#endif
213
Eric Andersencffd5022002-05-24 06:50:15 +0000214#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
215#define SHT_RELM SHT_RELA
216#define Elf32_RelM Elf32_Rela
217#define ELFCLASSM ELFCLASS32
218
219#define SYMBOL_PREFIX "_"
220#endif
221
222#ifndef SHT_RELM
223#error Sorry, but insmod.c does not yet support this architecture...
224#endif
225
226
Eric Andersen9f16d612000-06-12 23:11:16 +0000227//----------------------------------------------------------------------------
228//--------modutils module.h, lines 45-242
229//----------------------------------------------------------------------------
230
231/* Definitions for the Linux module syscall interface.
232 Copyright 1996, 1997 Linux International.
233
234 Contributed by Richard Henderson <rth@tamu.edu>
235
236 This file is part of the Linux modutils.
237
238 This program is free software; you can redistribute it and/or modify it
239 under the terms of the GNU General Public License as published by the
240 Free Software Foundation; either version 2 of the License, or (at your
241 option) any later version.
242
243 This program is distributed in the hope that it will be useful, but
244 WITHOUT ANY WARRANTY; without even the implied warranty of
245 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
246 General Public License for more details.
247
248 You should have received a copy of the GNU General Public License
249 along with this program; if not, write to the Free Software Foundation,
250 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
251
252
253#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000254static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000255
Glenn L McGrath759d7ec2003-09-03 00:42:58 +0000256#ident "$Id: insmod.c,v 1.103 2003/09/03 00:42:58 bug1 Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000257
258/* This file contains the structures used by the 2.0 and 2.1 kernels.
259 We do not use the kernel headers directly because we do not wish
260 to be dependant on a particular kernel version to compile insmod. */
261
262
263/*======================================================================*/
264/* The structures used by Linux 2.0. */
265
266/* The symbol format used by get_kernel_syms(2). */
267struct old_kernel_sym
268{
269 unsigned long value;
270 char name[60];
271};
272
273struct old_module_ref
274{
275 unsigned long module; /* kernel addresses */
276 unsigned long next;
277};
278
279struct old_module_symbol
280{
281 unsigned long addr;
282 unsigned long name;
283};
284
285struct old_symbol_table
286{
287 int size; /* total, including string table!!! */
288 int n_symbols;
289 int n_refs;
290 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
291 struct old_module_ref ref[0]; /* actual size defined by n_refs */
292};
293
294struct old_mod_routines
295{
296 unsigned long init;
297 unsigned long cleanup;
298};
299
300struct old_module
301{
302 unsigned long next;
303 unsigned long ref; /* the list of modules that refer to me */
304 unsigned long symtab;
305 unsigned long name;
306 int size; /* size of module in pages */
307 unsigned long addr; /* address of module */
308 int state;
309 unsigned long cleanup; /* cleanup routine */
310};
311
312/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000313static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000314
315int get_kernel_syms(struct old_kernel_sym *);
316int old_sys_init_module(const char *name, char *code, unsigned codesize,
317 struct old_mod_routines *, struct old_symbol_table *);
318
319/*======================================================================*/
320/* For sizeof() which are related to the module platform and not to the
321 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
322
323#define tgt_sizeof_char sizeof(char)
324#define tgt_sizeof_short sizeof(short)
325#define tgt_sizeof_int sizeof(int)
326#define tgt_sizeof_long sizeof(long)
327#define tgt_sizeof_char_p sizeof(char *)
328#define tgt_sizeof_void_p sizeof(void *)
329#define tgt_long long
330
331#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
332#undef tgt_sizeof_long
333#undef tgt_sizeof_char_p
334#undef tgt_sizeof_void_p
335#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000336static const int tgt_sizeof_long = 8;
337static const int tgt_sizeof_char_p = 8;
338static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000339#define tgt_long long long
340#endif
341
342/*======================================================================*/
343/* The structures used in Linux 2.1. */
344
345/* Note: new_module_symbol does not use tgt_long intentionally */
346struct new_module_symbol
347{
348 unsigned long value;
349 unsigned long name;
350};
351
352struct new_module_persist;
353
354struct new_module_ref
355{
356 unsigned tgt_long dep; /* kernel addresses */
357 unsigned tgt_long ref;
358 unsigned tgt_long next_ref;
359};
360
361struct new_module
362{
363 unsigned tgt_long size_of_struct; /* == sizeof(module) */
364 unsigned tgt_long next;
365 unsigned tgt_long name;
366 unsigned tgt_long size;
367
368 tgt_long usecount;
369 unsigned tgt_long flags; /* AUTOCLEAN et al */
370
371 unsigned nsyms;
372 unsigned ndeps;
373
374 unsigned tgt_long syms;
375 unsigned tgt_long deps;
376 unsigned tgt_long refs;
377 unsigned tgt_long init;
378 unsigned tgt_long cleanup;
379 unsigned tgt_long ex_table_start;
380 unsigned tgt_long ex_table_end;
381#ifdef __alpha__
382 unsigned tgt_long gp;
383#endif
384 /* Everything after here is extension. */
385 unsigned tgt_long persist_start;
386 unsigned tgt_long persist_end;
387 unsigned tgt_long can_unload;
388 unsigned tgt_long runsize;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000389#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen8ae319a2001-05-21 16:09:18 +0000390 const char *kallsyms_start; /* All symbols for kernel debugging */
391 const char *kallsyms_end;
392 const char *archdata_start; /* arch specific data for module */
393 const char *archdata_end;
394 const char *kernel_data; /* Reserved for kernel internal use */
395#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000396};
397
Eric Andersencffd5022002-05-24 06:50:15 +0000398#ifdef ARCHDATAM
399#define ARCHDATA_SEC_NAME ARCHDATAM
400#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000401#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000402#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000403#define KALLSYMS_SEC_NAME "__kallsyms"
404
405
Eric Andersen9f16d612000-06-12 23:11:16 +0000406struct new_module_info
407{
408 unsigned long addr;
409 unsigned long size;
410 unsigned long flags;
411 long usecount;
412};
413
414/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000415static const int NEW_MOD_RUNNING = 1;
416static const int NEW_MOD_DELETED = 2;
417static const int NEW_MOD_AUTOCLEAN = 4;
418static const int NEW_MOD_VISITED = 8;
419static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000420
Eric Andersen64c8b172001-04-05 07:33:10 +0000421int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000422int query_module(const char *name, int which, void *buf, size_t bufsize,
423 size_t *ret);
424
425/* Values for query_module's which. */
426
Mark Whitley59ab0252001-01-23 22:30:04 +0000427static const int QM_MODULES = 1;
428static const int QM_DEPS = 2;
429static const int QM_REFS = 3;
430static const int QM_SYMBOLS = 4;
431static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000432
433/*======================================================================*/
434/* The system calls unchanged between 2.0 and 2.1. */
435
436unsigned long create_module(const char *, size_t);
437int delete_module(const char *);
438
439
440#endif /* module.h */
441
442//----------------------------------------------------------------------------
443//--------end of modutils module.h
444//----------------------------------------------------------------------------
445
446
447
448//----------------------------------------------------------------------------
449//--------modutils obj.h, lines 253-462
450//----------------------------------------------------------------------------
451
452/* Elf object file loading and relocation routines.
453 Copyright 1996, 1997 Linux International.
454
455 Contributed by Richard Henderson <rth@tamu.edu>
456
457 This file is part of the Linux modutils.
458
459 This program is free software; you can redistribute it and/or modify it
460 under the terms of the GNU General Public License as published by the
461 Free Software Foundation; either version 2 of the License, or (at your
462 option) any later version.
463
464 This program is distributed in the hope that it will be useful, but
465 WITHOUT ANY WARRANTY; without even the implied warranty of
466 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
467 General Public License for more details.
468
469 You should have received a copy of the GNU General Public License
470 along with this program; if not, write to the Free Software Foundation,
471 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
472
473
474#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000475static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000476
Glenn L McGrath759d7ec2003-09-03 00:42:58 +0000477#ident "$Id: insmod.c,v 1.103 2003/09/03 00:42:58 bug1 Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000478
479/* The relocatable object is manipulated using elfin types. */
480
481#include <stdio.h>
482#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000483#include <endian.h>
484
485#if __BYTE_ORDER == __LITTLE_ENDIAN
486#define ELFDATAM ELFDATA2LSB
487#elif __BYTE_ORDER == __BIG_ENDIAN
488#define ELFDATAM ELFDATA2MSB
489#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000490
Eric Andersen9f16d612000-06-12 23:11:16 +0000491#ifndef ElfW
492# if ELFCLASSM == ELFCLASS32
493# define ElfW(x) Elf32_ ## x
494# define ELFW(x) ELF32_ ## x
495# else
496# define ElfW(x) Elf64_ ## x
497# define ELFW(x) ELF64_ ## x
498# endif
499#endif
500
Eric Andersen85e5e722003-07-22 08:56:55 +0000501/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000502#ifndef ELF32_ST_INFO
503# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
504#endif
505
506#ifndef ELF64_ST_INFO
507# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
508#endif
509
510struct obj_string_patch;
511struct obj_symbol_patch;
512
513struct obj_section
514{
515 ElfW(Shdr) header;
516 const char *name;
517 char *contents;
518 struct obj_section *load_next;
519 int idx;
520};
521
522struct obj_symbol
523{
524 struct obj_symbol *next; /* hash table link */
525 const char *name;
526 unsigned long value;
527 unsigned long size;
528 int secidx; /* the defining section index/module */
529 int info;
530 int ksymidx; /* for export to the kernel symtab */
531 int referenced; /* actually used in the link */
532};
533
534/* Hardcode the hash table size. We shouldn't be needing so many
535 symbols that we begin to degrade performance, and we get a big win
536 by giving the compiler a constant divisor. */
537
538#define HASH_BUCKETS 521
539
540struct obj_file
541{
542 ElfW(Ehdr) header;
543 ElfW(Addr) baseaddr;
544 struct obj_section **sections;
545 struct obj_section *load_order;
546 struct obj_section **load_order_search_start;
547 struct obj_string_patch *string_patches;
548 struct obj_symbol_patch *symbol_patches;
549 int (*symbol_cmp)(const char *, const char *);
550 unsigned long (*symbol_hash)(const char *);
551 unsigned long local_symtab_size;
552 struct obj_symbol **local_symtab;
553 struct obj_symbol *symtab[HASH_BUCKETS];
554};
555
556enum obj_reloc
557{
558 obj_reloc_ok,
559 obj_reloc_overflow,
560 obj_reloc_dangerous,
561 obj_reloc_unhandled
562};
563
564struct obj_string_patch
565{
566 struct obj_string_patch *next;
567 int reloc_secidx;
568 ElfW(Addr) reloc_offset;
569 ElfW(Addr) string_offset;
570};
571
572struct obj_symbol_patch
573{
574 struct obj_symbol_patch *next;
575 int reloc_secidx;
576 ElfW(Addr) reloc_offset;
577 struct obj_symbol *sym;
578};
579
580
581/* Generic object manipulation routines. */
582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000584
Eric Andersen044228d2001-07-17 01:12:36 +0000585static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000586
Eric Andersen044228d2001-07-17 01:12:36 +0000587static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000588 const char *name);
589
Eric Andersen044228d2001-07-17 01:12:36 +0000590static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000591 struct obj_symbol *sym);
592
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000593#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000594static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000595 int (*cmp)(const char *, const char *),
596 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000597#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000600 const char *name);
601
Eric Andersen044228d2001-07-17 01:12:36 +0000602static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000603 struct obj_section *sec);
604
Eric Andersen044228d2001-07-17 01:12:36 +0000605static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000606 const char *name,
607 unsigned long align,
608 unsigned long size);
609
Eric Andersen044228d2001-07-17 01:12:36 +0000610static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000611 const char *name,
612 unsigned long align,
613 unsigned long size);
614
Eric Andersen044228d2001-07-17 01:12:36 +0000615static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000618 const char *string);
619
Eric Andersen6d139642001-12-29 04:15:13 +0000620#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000621static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000622 struct obj_symbol *sym);
Eric Andersen6d139642001-12-29 04:15:13 +0000623#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000628
Eric Andersen044228d2001-07-17 01:12:36 +0000629static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000630
Eric Andersen044228d2001-07-17 01:12:36 +0000631static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000634
Eric Andersen044228d2001-07-17 01:12:36 +0000635static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000636
637/* Architecture specific manipulation routines. */
638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000642
Eric Andersen044228d2001-07-17 01:12:36 +0000643static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000646 struct obj_section *targsec,
647 struct obj_section *symsec,
648 struct obj_symbol *sym,
649 ElfW(RelM) *rel, ElfW(Addr) value);
650
Eric Andersencffd5022002-05-24 06:50:15 +0000651static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000652
Glenn L McGrath759515c2003-08-30 06:00:33 +0000653static int obj_gpl_license(struct obj_file *f, const char **license);
654
Eric Andersen6d139642001-12-29 04:15:13 +0000655#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000656static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen6d139642001-12-29 04:15:13 +0000657#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000658
659#endif /* obj.h */
660//----------------------------------------------------------------------------
661//--------end of modutils obj.h
662//----------------------------------------------------------------------------
663
664
Miles Baderae28b042002-04-01 09:34:25 +0000665/* SPFX is always a string, so it can be concatenated to string constants. */
666#ifdef SYMBOL_PREFIX
667#define SPFX SYMBOL_PREFIX
668#else
669#define SPFX ""
670#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000671
Erik Andersen02104321999-12-17 18:57:34 +0000672
Erik Andersend387d011999-12-21 02:55:11 +0000673#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000674static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000675
Eric Andersen9f16d612000-06-12 23:11:16 +0000676/*======================================================================*/
677
Eric Andersen044228d2001-07-17 01:12:36 +0000678static int flag_force_load = 0;
679static int flag_autoclean = 0;
680static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000681static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000682static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000683
684
685/*======================================================================*/
686
Eric Andersencffd5022002-05-24 06:50:15 +0000687#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000688
Eric Andersencffd5022002-05-24 06:50:15 +0000689struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000690{
Eric Andersencffd5022002-05-24 06:50:15 +0000691 struct arch_list_entry *next;
692 CONFIG_LIST_ARCHTYPE addend;
693 int offset;
694 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000695};
Eric Andersencffd5022002-05-24 06:50:15 +0000696
Eric Andersen21adca72000-12-06 18:18:26 +0000697#endif
698
Eric Andersencffd5022002-05-24 06:50:15 +0000699#if defined(CONFIG_USE_SINGLE)
700
701struct arch_single_entry
702{
Eric Andersen9f16d612000-06-12 23:11:16 +0000703 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000704 int inited : 1;
705 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000706};
Eric Andersencffd5022002-05-24 06:50:15 +0000707
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000708#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000709
Eric Andersen2bf658d2001-02-24 20:01:53 +0000710#if defined(__mips__)
711struct mips_hi16
712{
713 struct mips_hi16 *next;
714 Elf32_Addr *addr;
715 Elf32_Addr value;
716};
717#endif
718
Eric Andersenfe4208f2000-09-24 03:44:29 +0000719struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000720 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000721#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000722 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000723#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000724#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000725 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000726#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000727#if defined(__mips__)
728 struct mips_hi16 *mips_hi16_list;
729#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000730};
731
Eric Andersenfe4208f2000-09-24 03:44:29 +0000732struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000733 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000734#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000735#if defined(CONFIG_USE_PLT_LIST)
736 struct arch_list_entry *pltent;
737#else
738 struct arch_single_entry pltent;
739#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000740#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000741#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000742 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000743#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000744};
745
746
Eric Andersen9f16d612000-06-12 23:11:16 +0000747struct external_module {
748 const char *name;
749 ElfW(Addr) addr;
750 int used;
751 size_t nsyms;
752 struct new_module_symbol *syms;
753};
754
Eric Andersen044228d2001-07-17 01:12:36 +0000755static struct new_module_symbol *ksyms;
756static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000757
Eric Andersen044228d2001-07-17 01:12:36 +0000758static struct external_module *ext_modules;
759static int n_ext_modules;
760static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000761extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000762
Eric Andersen61f83052002-06-22 17:15:42 +0000763static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000764static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000765
Eric Andersenfe4208f2000-09-24 03:44:29 +0000766
Erik Andersen02104321999-12-17 18:57:34 +0000767
Eric Andersen9f16d612000-06-12 23:11:16 +0000768/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000769
Eric Andersen9f16d612000-06-12 23:11:16 +0000770
Eric Andersen14d35432001-05-14 17:07:32 +0000771static int check_module_name_match(const char *filename, struct stat *statbuf,
772 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000773{
Eric Andersen14d35432001-05-14 17:07:32 +0000774 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000775
Eric Andersen14d35432001-05-14 17:07:32 +0000776 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000777 return (FALSE);
778 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000779 char *tmp, *tmp1 = bb_xstrdup(filename);
780 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000781 if (strcmp(tmp, fullname) == 0) {
782 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000783 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000784 m_filename = bb_xstrdup(filename);
Eric Andersen14d35432001-05-14 17:07:32 +0000785 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000786 }
Eric Andersen14d35432001-05-14 17:07:32 +0000787 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000788 }
Eric Andersen14d35432001-05-14 17:07:32 +0000789 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000790}
791
Erik Andersen02104321999-12-17 18:57:34 +0000792
Eric Andersen9f16d612000-06-12 23:11:16 +0000793/*======================================================================*/
794
Eric Andersen044228d2001-07-17 01:12:36 +0000795static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000796{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000797 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000798 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000799
Eric Andersencffd5022002-05-24 06:50:15 +0000800 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000801
Eric Andersen9f16d612000-06-12 23:11:16 +0000802 return &f->root;
803}
804
Eric Andersen044228d2001-07-17 01:12:36 +0000805static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000806{
807 return xmalloc(sizeof(struct obj_section));
808}
809
Eric Andersen044228d2001-07-17 01:12:36 +0000810static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000811{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000813 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000814
Eric Andersencffd5022002-05-24 06:50:15 +0000815 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816
Eric Andersen9f16d612000-06-12 23:11:16 +0000817 return &sym->root;
818}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000819
Eric Andersen044228d2001-07-17 01:12:36 +0000820static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000821arch_apply_relocation(struct obj_file *f,
822 struct obj_section *targsec,
823 struct obj_section *symsec,
824 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000825 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000826{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000827 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000828 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000829 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
830 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000831#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
832 struct arch_symbol *isym = (struct arch_symbol *) sym;
833#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000834#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000835 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000836#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000837#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000838 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000839 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000840#if defined(CONFIG_USE_PLT_LIST)
841 struct arch_list_entry *pe;
842#else
843 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000844#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000845#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000846
847 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000848
Eric Andersencffd5022002-05-24 06:50:15 +0000849
850#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000851 case R_ARM_NONE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000852 break;
853
Eric Andersen21adca72000-12-06 18:18:26 +0000854 case R_ARM_ABS32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000855 *loc += v;
856 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000857
858 case R_ARM_GOT32:
859 goto bb_use_got;
Miles Baderae28b042002-04-01 09:34:25 +0000860
Eric Andersencffd5022002-05-24 06:50:15 +0000861 case R_ARM_GOTPC:
862 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
863 * (which is .got) similar to branch,
864 * but is full 32 bits relative */
865
866 assert(got);
867 *loc += got - dot;
868 break;
869
870 case R_ARM_PC24:
871 case R_ARM_PLT32:
872 goto bb_use_plt;
873
874 case R_ARM_GOTOFF: /* address relative to the got */
875 assert(got);
876 *loc += v - got;
877 break;
878
Eric Andersenbf77f612003-01-23 06:02:39 +0000879#elif defined(__s390__)
880 case R_390_32:
881 *(unsigned int *) loc += v;
882 break;
883 case R_390_16:
884 *(unsigned short *) loc += v;
885 break;
886 case R_390_8:
887 *(unsigned char *) loc += v;
888 break;
889
890 case R_390_PC32:
891 *(unsigned int *) loc += v - dot;
892 break;
893 case R_390_PC16DBL:
894 *(unsigned short *) loc += (v - dot) >> 1;
895 break;
896 case R_390_PC16:
897 *(unsigned short *) loc += v - dot;
898 break;
899
900 case R_390_PLT32:
901 case R_390_PLT16DBL:
902 /* find the plt entry and initialize it. */
903 assert(isym != NULL);
904 pe = (struct arch_single_entry *) &isym->pltent;
905 assert(pe->allocated);
906 if (pe->inited == 0) {
907 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
908 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
909 ip[1] = 0x100607f1;
910 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
911 ip[2] = v - 2;
912 else
913 ip[2] = v;
914 pe->inited = 1;
915 }
916
917 /* Insert relative distance to target. */
918 v = plt + pe->offset - dot;
919 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
920 *(unsigned int *) loc = (unsigned int) v;
921 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
922 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
923 break;
924
925 case R_390_GLOB_DAT:
926 case R_390_JMP_SLOT:
927 *loc = v;
928 break;
929
930 case R_390_RELATIVE:
931 *loc += f->baseaddr;
932 break;
933
934 case R_390_GOTPC:
935 assert(got != 0);
936 *(unsigned long *) loc += got - dot;
937 break;
938
939 case R_390_GOT12:
940 case R_390_GOT16:
941 case R_390_GOT32:
942 assert(isym != NULL);
943 assert(got != 0);
944 if (!isym->gotent.inited)
945 {
946 isym->gotent.inited = 1;
947 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
948 }
949 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
950 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
951 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
952 *(unsigned short *) loc += isym->gotent.offset;
953 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
954 *(unsigned int *) loc += isym->gotent.offset;
955 break;
956
957 case R_390_GOTOFF:
958 assert(got != 0);
959 *loc += v - got;
960 break;
961
Eric Andersencffd5022002-05-24 06:50:15 +0000962#elif defined(__i386__)
963
964 case R_386_NONE:
965 break;
966
967 case R_386_32:
968 *loc += v;
969 break;
970
971 case R_386_PLT32:
972 case R_386_PC32:
973 *loc += v - dot;
974 break;
975
976 case R_386_GLOB_DAT:
977 case R_386_JMP_SLOT:
978 *loc = v;
979 break;
980
981 case R_386_RELATIVE:
982 *loc += f->baseaddr;
983 break;
984
985 case R_386_GOTPC:
986 assert(got != 0);
987 *loc += got - dot;
988 break;
989
990 case R_386_GOT32:
991 goto bb_use_got;
992
993 case R_386_GOTOFF:
994 assert(got != 0);
995 *loc += v - got;
996 break;
997
998#elif defined(__mc68000__)
999
1000 case R_68K_NONE:
1001 break;
1002
1003 case R_68K_32:
1004 *loc += v;
1005 break;
1006
1007 case R_68K_8:
1008 if (v > 0xff) {
1009 ret = obj_reloc_overflow;
1010 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00001011 *(char *)loc = v;
1012 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001013
1014 case R_68K_16:
1015 if (v > 0xffff) {
1016 ret = obj_reloc_overflow;
1017 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00001018 *(short *)loc = v;
1019 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001020
Eric Andersencffd5022002-05-24 06:50:15 +00001021 case R_68K_PC8:
1022 v -= dot;
1023 if ((Elf32_Sword)v > 0x7f ||
1024 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1025 ret = obj_reloc_overflow;
1026 }
1027 *(char *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001028 break;
1029
Eric Andersencffd5022002-05-24 06:50:15 +00001030 case R_68K_PC16:
1031 v -= dot;
1032 if ((Elf32_Sword)v > 0x7fff ||
1033 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1034 ret = obj_reloc_overflow;
1035 }
1036 *(short *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001037 break;
1038
Eric Andersencffd5022002-05-24 06:50:15 +00001039 case R_68K_PC32:
1040 *(int *)loc = v - dot;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001041 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001042
Eric Andersencffd5022002-05-24 06:50:15 +00001043 case R_68K_GLOB_DAT:
1044 case R_68K_JMP_SLOT:
1045 *loc = v;
1046 break;
1047
1048 case R_68K_RELATIVE:
1049 *(int *)loc += f->baseaddr;
1050 break;
1051
1052 case R_68K_GOT32:
1053 goto bb_use_got;
1054
1055 case R_68K_GOTOFF:
1056 assert(got != 0);
1057 *loc += v - got;
1058 break;
1059
1060#elif defined(__mips__)
1061
1062 case R_MIPS_NONE:
1063 break;
1064
1065 case R_MIPS_32:
1066 *loc += v;
1067 break;
1068
Eric Andersen2bf658d2001-02-24 20:01:53 +00001069 case R_MIPS_26:
1070 if (v % 4)
1071 ret = obj_reloc_dangerous;
1072 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1073 ret = obj_reloc_overflow;
1074 *loc =
1075 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1076 0x03ffffff);
1077 break;
1078
1079 case R_MIPS_HI16:
1080 {
1081 struct mips_hi16 *n;
1082
1083 /* We cannot relocate this one now because we don't know the value
1084 of the carry we need to add. Save the information, and let LO16
1085 do the actual relocation. */
1086 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1087 n->addr = loc;
1088 n->value = v;
1089 n->next = ifile->mips_hi16_list;
1090 ifile->mips_hi16_list = n;
1091 break;
1092 }
1093
1094 case R_MIPS_LO16:
1095 {
1096 unsigned long insnlo = *loc;
1097 Elf32_Addr val, vallo;
1098
1099 /* Sign extend the addend we extract from the lo insn. */
1100 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1101
1102 if (ifile->mips_hi16_list != NULL) {
1103 struct mips_hi16 *l;
1104
1105 l = ifile->mips_hi16_list;
1106 while (l != NULL) {
1107 struct mips_hi16 *next;
1108 unsigned long insn;
1109
1110 /* The value for the HI16 had best be the same. */
1111 assert(v == l->value);
1112
1113 /* Do the HI16 relocation. Note that we actually don't
1114 need to know anything about the LO16 itself, except where
1115 to find the low 16 bits of the addend needed by the LO16. */
1116 insn = *l->addr;
1117 val =
1118 ((insn & 0xffff) << 16) +
1119 vallo;
1120 val += v;
1121
1122 /* Account for the sign extension that will happen in the
1123 low bits. */
1124 val =
1125 ((val >> 16) +
1126 ((val & 0x8000) !=
1127 0)) & 0xffff;
1128
1129 insn = (insn & ~0xffff) | val;
1130 *l->addr = insn;
1131
1132 next = l->next;
1133 free(l);
1134 l = next;
1135 }
1136
1137 ifile->mips_hi16_list = NULL;
1138 }
1139
1140 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1141 val = v + vallo;
1142 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1143 *loc = insnlo;
1144 break;
1145 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001146
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001147#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001148
1149 case R_PPC_ADDR16_HA:
1150 *(unsigned short *)loc = (v + 0x8000) >> 16;
1151 break;
1152
1153 case R_PPC_ADDR16_HI:
1154 *(unsigned short *)loc = v >> 16;
1155 break;
1156
1157 case R_PPC_ADDR16_LO:
1158 *(unsigned short *)loc = v;
1159 break;
1160
1161 case R_PPC_REL24:
1162 goto bb_use_plt;
1163
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001164 case R_PPC_REL32:
1165 *loc = v - dot;
1166 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001167
1168 case R_PPC_ADDR32:
1169 *loc = v;
1170 break;
1171
1172#elif defined(__sh__)
1173
1174 case R_SH_NONE:
1175 break;
1176
1177 case R_SH_DIR32:
1178 *loc += v;
1179 break;
1180
1181 case R_SH_REL32:
1182 *loc += v - dot;
1183 break;
1184
1185 case R_SH_PLT32:
1186 *loc = v - dot;
1187 break;
1188
1189 case R_SH_GLOB_DAT:
1190 case R_SH_JMP_SLOT:
1191 *loc = v;
1192 break;
1193
1194 case R_SH_RELATIVE:
1195 *loc = f->baseaddr + rel->r_addend;
1196 break;
1197
1198 case R_SH_GOTPC:
1199 assert(got != 0);
1200 *loc = got - dot + rel->r_addend;
1201 break;
1202
1203 case R_SH_GOT32:
1204 goto bb_use_got;
1205
1206 case R_SH_GOTOFF:
1207 assert(got != 0);
1208 *loc = v - got;
1209 break;
1210
Eric Andersenbf833552003-08-13 19:56:33 +00001211#if defined(__SH5__)
1212 case R_SH_IMM_MEDLOW16:
1213 case R_SH_IMM_LOW16:
1214 {
1215 Elf32_Addr word;
1216
1217 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1218 v >>= 16;
1219
1220 /*
1221 * movi and shori have the format:
1222 *
1223 * | op | imm | reg | reserved |
1224 * 31..26 25..10 9.. 4 3 .. 0
1225 *
1226 * so we simply mask and or in imm.
1227 */
1228 word = *loc & ~0x3fffc00;
1229 word |= (v & 0xffff) << 10;
1230
1231 *loc = word;
1232
1233 break;
1234 }
1235
1236 case R_SH_IMM_MEDLOW16_PCREL:
1237 case R_SH_IMM_LOW16_PCREL:
1238 {
1239 Elf32_Addr word;
1240
1241 word = *loc & ~0x3fffc00;
1242
1243 v -= dot;
1244
1245 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1246 v >>= 16;
1247
1248 word |= (v & 0xffff) << 10;
1249
1250 *loc = word;
1251
1252 break;
1253 }
1254#endif /* __SH5__ */
1255#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001256
Eric Andersencffd5022002-05-24 06:50:15 +00001257 default:
1258 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1259 ret = obj_reloc_unhandled;
1260 break;
1261
1262#if defined (__v850e__)
1263 case R_V850_NONE:
1264 break;
1265
1266 case R_V850_32:
1267 /* We write two shorts instead of a long because even
1268 32-bit insns only need half-word alignment, but
1269 32-bit data needs to be long-word aligned. */
1270 v += ((unsigned short *)loc)[0];
1271 v += ((unsigned short *)loc)[1] << 16;
1272 ((unsigned short *)loc)[0] = v & 0xffff;
1273 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1274 break;
1275
1276 case R_V850_22_PCREL:
1277 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001278#endif
1279
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001280#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001281
Eric Andersencffd5022002-05-24 06:50:15 +00001282 bb_use_plt:
1283
Eric Andersen21adca72000-12-06 18:18:26 +00001284 /* find the plt entry and initialize it if necessary */
1285 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001286
Eric Andersencffd5022002-05-24 06:50:15 +00001287#if defined(CONFIG_USE_PLT_LIST)
1288 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1289 pe = pe->next;
1290 assert(pe != NULL);
1291#else
1292 pe = &isym->pltent;
1293#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001294
Eric Andersen21adca72000-12-06 18:18:26 +00001295 if (! pe->inited) {
1296 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001297
1298 /* generate some machine code */
1299
1300#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001301 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1302 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001303#endif
1304#if defined(__powerpc__)
1305 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1306 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1307 ip[2] = 0x7d6903a6; /* mtctr r11 */
1308 ip[3] = 0x4e800420; /* bctr */
1309#endif
Miles Baderae28b042002-04-01 09:34:25 +00001310#if defined (__v850e__)
1311 /* We have to trash a register, so we assume that any control
1312 transfer more than 21-bits away must be a function call
1313 (so we can use a call-clobbered register). */
1314 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1315 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
1316#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001317 pe->inited = 1;
1318 }
1319
1320 /* relative distance to target */
1321 v -= dot;
1322 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001323#if defined (__arm__) || defined (__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001324 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001325#elif defined (__v850e__)
1326 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
1327#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001328 /* go via the plt */
1329 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001330
1331#if defined (__v850e__)
1332 if (v & 1)
1333#else
Eric Andersen21adca72000-12-06 18:18:26 +00001334 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001335#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001336 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001337
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001338 /* merge the offset into the instruction. */
1339#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001340 /* Convert to words. */
1341 v >>= 2;
1342
Eric Andersen21adca72000-12-06 18:18:26 +00001343 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001344#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001345#if defined(__powerpc__)
1346 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1347#endif
Miles Baderae28b042002-04-01 09:34:25 +00001348#if defined (__v850e__)
1349 /* We write two shorts instead of a long because even 32-bit insns
1350 only need half-word alignment, but the 32-bit data write needs
1351 to be long-word aligned. */
1352 ((unsigned short *)loc)[0] =
1353 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1354 | ((v >> 16) & 0x3f); /* offs high part */
1355 ((unsigned short *)loc)[1] =
1356 (v & 0xffff); /* offs low part */
1357#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001358 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001359#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001360
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001361#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001362 bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001363
Eric Andersen9f16d612000-06-12 23:11:16 +00001364 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001365 /* needs an entry in the .got: set it, once */
Eric Andersencffd5022002-05-24 06:50:15 +00001366 if (!isym->gotent.inited) {
1367 isym->gotent.inited = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001368 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001369 }
Eric Andersen21adca72000-12-06 18:18:26 +00001370 /* make the reloc with_respect_to_.got */
1371#if defined(__sh__)
1372 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001373#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001374 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001375#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001376 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001377
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001378#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001379 }
1380
1381 return ret;
1382}
1383
Eric Andersencffd5022002-05-24 06:50:15 +00001384
1385#if defined(CONFIG_USE_LIST)
1386
1387static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1388 int offset, int size)
1389{
1390 struct arch_list_entry *pe;
1391
1392 for (pe = *list; pe != NULL; pe = pe->next) {
1393 if (pe->addend == rel->r_addend) {
1394 break;
1395 }
1396 }
1397
1398 if (pe == NULL) {
1399 pe = xmalloc(sizeof(struct arch_list_entry));
1400 pe->next = *list;
1401 pe->addend = rel->r_addend;
1402 pe->offset = offset;
1403 pe->inited = 0;
1404 *list = pe;
1405 return size;
1406 }
1407 return 0;
1408}
1409
1410#endif
1411
1412#if defined(CONFIG_USE_SINGLE)
1413
1414static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1415 int offset, int size)
1416{
1417 if (single->allocated == 0) {
1418 single->allocated = 1;
1419 single->offset = offset;
1420 single->inited = 0;
1421 return size;
1422 }
1423 return 0;
1424}
1425
1426#endif
1427
1428#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1429
1430static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
1431 int offset, int size)
1432{
1433 struct obj_section *myrelsec = obj_find_section(f, name);
1434
1435 if (offset == 0) {
1436 offset += size;
1437 }
1438
1439 if (myrelsec) {
1440 obj_extend_section(myrelsec, offset);
1441 } else {
1442 myrelsec = obj_create_alloced_section(f, name,
1443 size, offset);
1444 assert(myrelsec);
1445 }
1446
1447 return myrelsec;
1448}
1449
1450#endif
1451
1452static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001453{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001454#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001455 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001456 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001457#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001458 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001459#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001460#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001461 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001462#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001463 struct obj_section *relsec, *symsec, *strsec;
1464 ElfW(RelM) *rel, *relend;
1465 ElfW(Sym) *symtab, *extsym;
1466 const char *strtab, *name;
1467 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001468
Eric Andersen21adca72000-12-06 18:18:26 +00001469 for (i = 0; i < f->header.e_shnum; ++i) {
1470 relsec = f->sections[i];
1471 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001472 continue;
1473
Eric Andersen21adca72000-12-06 18:18:26 +00001474 symsec = f->sections[relsec->header.sh_link];
1475 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001476
Eric Andersen21adca72000-12-06 18:18:26 +00001477 rel = (ElfW(RelM) *) relsec->contents;
1478 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1479 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001480 strtab = (const char *) strsec->contents;
1481
1482 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001483 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001484
Eric Andersencffd5022002-05-24 06:50:15 +00001485#if defined(CONFIG_USE_GOT_ENTRIES)
1486 got_allocate = 0;
1487#endif
1488#if defined(CONFIG_USE_PLT_ENTRIES)
1489 plt_allocate = 0;
1490#endif
1491
Eric Andersen9f16d612000-06-12 23:11:16 +00001492 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001493#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001494 case R_ARM_PC24:
1495 case R_ARM_PLT32:
Eric Andersencffd5022002-05-24 06:50:15 +00001496 plt_allocate = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001497 break;
1498
Eric Andersen21adca72000-12-06 18:18:26 +00001499 case R_ARM_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001500 case R_ARM_GOTPC:
1501 got_needed = 1;
1502 continue;
1503
1504 case R_ARM_GOT32:
1505 got_allocate = 1;
1506 break;
1507
Eric Andersen21adca72000-12-06 18:18:26 +00001508#elif defined(__i386__)
1509 case R_386_GOTPC:
1510 case R_386_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001511 got_needed = 1;
1512 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001513
Eric Andersencffd5022002-05-24 06:50:15 +00001514 case R_386_GOT32:
1515 got_allocate = 1;
1516 break;
1517
1518#elif defined(__powerpc__)
1519 case R_PPC_REL24:
1520 plt_allocate = 1;
1521 break;
1522
1523#elif defined(__mc68000__)
1524 case R_68K_GOT32:
1525 got_allocate = 1;
1526 break;
1527
1528 case R_68K_GOTOFF:
1529 got_needed = 1;
1530 continue;
1531
1532#elif defined(__sh__)
1533 case R_SH_GOT32:
1534 got_allocate = 1;
1535 break;
1536
1537 case R_SH_GOTPC:
1538 case R_SH_GOTOFF:
1539 got_needed = 1;
1540 continue;
1541
1542#elif defined (__v850e__)
1543 case R_V850_22_PCREL:
1544 plt_needed = 1;
1545 break;
1546
1547#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001548 default:
1549 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001550 }
1551
Eric Andersen21adca72000-12-06 18:18:26 +00001552 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001553 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001554 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001555 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001556 }
1557 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001558#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001559 if (got_allocate) {
1560 got_offset += arch_single_init(
1561 rel, &intsym->gotent,
1562 got_offset, CONFIG_GOT_ENTRY_SIZE);
1563
1564 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001565 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001566#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001567#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001568 if (plt_allocate) {
1569#if defined(CONFIG_USE_PLT_LIST)
1570 plt_offset += arch_list_add(
1571 rel, &intsym->pltent,
1572 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1573#else
1574 plt_offset += arch_single_init(
1575 rel, &intsym->pltent,
1576 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1577#endif
1578 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001579 }
1580#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001581 }
Miles Baderae28b042002-04-01 09:34:25 +00001582 }
Eric Andersen21adca72000-12-06 18:18:26 +00001583
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001584#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001585 if (got_needed) {
1586 ifile->got = arch_xsect_init(f, ".got", got_offset,
1587 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001588 }
Eric Andersen21adca72000-12-06 18:18:26 +00001589#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001590
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001591#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001592 if (plt_needed) {
1593 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
1594 CONFIG_PLT_ENTRY_SIZE);
1595 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001596#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001597
1598#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001599}
1600
Eric Andersen6d139642001-12-29 04:15:13 +00001601#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00001602static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001603{
1604 return 1;
1605}
Eric Andersen6d139642001-12-29 04:15:13 +00001606#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001607
1608/*======================================================================*/
1609
1610/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001611static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001612{
1613 unsigned long h = 0;
1614 unsigned long g;
1615 unsigned char ch;
1616
1617 while (n > 0) {
1618 ch = *name++;
1619 h = (h << 4) + ch;
1620 if ((g = (h & 0xf0000000)) != 0) {
1621 h ^= g >> 24;
1622 h &= ~g;
1623 }
1624 n--;
1625 }
1626 return h;
1627}
1628
Eric Andersen044228d2001-07-17 01:12:36 +00001629static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001630{
1631 return obj_elf_hash_n(name, strlen(name));
1632}
1633
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001634#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001635/* String comparison for non-co-versioned kernel and module. */
1636
1637static int ncv_strcmp(const char *a, const char *b)
1638{
1639 size_t alen = strlen(a), blen = strlen(b);
1640
1641 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1642 return strncmp(a, b, alen);
1643 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1644 return strncmp(a, b, blen);
1645 else
1646 return strcmp(a, b);
1647}
1648
1649/* String hashing for non-co-versioned kernel and module. Here
1650 we are simply forced to drop the crc from the hash. */
1651
1652static unsigned long ncv_symbol_hash(const char *str)
1653{
1654 size_t len = strlen(str);
1655 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1656 len -= 10;
1657 return obj_elf_hash_n(str, len);
1658}
1659
Eric Andersen044228d2001-07-17 01:12:36 +00001660static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001661obj_set_symbol_compare(struct obj_file *f,
1662 int (*cmp) (const char *, const char *),
1663 unsigned long (*hash) (const char *))
1664{
1665 if (cmp)
1666 f->symbol_cmp = cmp;
1667 if (hash) {
1668 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1669 int i;
1670
1671 f->symbol_hash = hash;
1672
1673 memcpy(tmptab, f->symtab, sizeof(tmptab));
1674 memset(f->symtab, 0, sizeof(f->symtab));
1675
1676 for (i = 0; i < HASH_BUCKETS; ++i)
1677 for (sym = tmptab[i]; sym; sym = next) {
1678 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1679 next = sym->next;
1680 sym->next = f->symtab[h];
1681 f->symtab[h] = sym;
1682 }
1683 }
1684}
1685
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001686#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001687
Eric Andersen044228d2001-07-17 01:12:36 +00001688static struct obj_symbol *
1689obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001690 unsigned long symidx, int info,
1691 int secidx, ElfW(Addr) value,
1692 unsigned long size)
1693{
1694 struct obj_symbol *sym;
1695 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1696 int n_type = ELFW(ST_TYPE) (info);
1697 int n_binding = ELFW(ST_BIND) (info);
1698
1699 for (sym = f->symtab[hash]; sym; sym = sym->next)
1700 if (f->symbol_cmp(sym->name, name) == 0) {
1701 int o_secidx = sym->secidx;
1702 int o_info = sym->info;
1703 int o_type = ELFW(ST_TYPE) (o_info);
1704 int o_binding = ELFW(ST_BIND) (o_info);
1705
1706 /* A redefinition! Is it legal? */
1707
1708 if (secidx == SHN_UNDEF)
1709 return sym;
1710 else if (o_secidx == SHN_UNDEF)
1711 goto found;
1712 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1713 /* Cope with local and global symbols of the same name
1714 in the same object file, as might have been created
1715 by ld -r. The only reason locals are now seen at this
1716 level at all is so that we can do semi-sensible things
1717 with parameters. */
1718
1719 struct obj_symbol *nsym, **p;
1720
1721 nsym = arch_new_symbol();
1722 nsym->next = sym->next;
1723 nsym->ksymidx = -1;
1724
1725 /* Excise the old (local) symbol from the hash chain. */
1726 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1727 continue;
1728 *p = sym = nsym;
1729 goto found;
1730 } else if (n_binding == STB_LOCAL) {
1731 /* Another symbol of the same name has already been defined.
1732 Just add this to the local table. */
1733 sym = arch_new_symbol();
1734 sym->next = NULL;
1735 sym->ksymidx = -1;
1736 f->local_symtab[symidx] = sym;
1737 goto found;
1738 } else if (n_binding == STB_WEAK)
1739 return sym;
1740 else if (o_binding == STB_WEAK)
1741 goto found;
1742 /* Don't unify COMMON symbols with object types the programmer
1743 doesn't expect. */
1744 else if (secidx == SHN_COMMON
1745 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1746 return sym;
1747 else if (o_secidx == SHN_COMMON
1748 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1749 goto found;
1750 else {
1751 /* Don't report an error if the symbol is coming from
1752 the kernel or some external module. */
1753 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001754 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001755 return sym;
1756 }
1757 }
1758
1759 /* Completely new symbol. */
1760 sym = arch_new_symbol();
1761 sym->next = f->symtab[hash];
1762 f->symtab[hash] = sym;
1763 sym->ksymidx = -1;
1764
Eric Andersen66ca9482001-06-28 21:36:06 +00001765 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1766 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001767 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001768 name, (long) symidx, (long) f->local_symtab_size);
1769 else
1770 f->local_symtab[symidx] = sym;
1771 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001772
1773 found:
1774 sym->name = name;
1775 sym->value = value;
1776 sym->size = size;
1777 sym->secidx = secidx;
1778 sym->info = info;
1779
1780 return sym;
1781}
1782
Eric Andersen044228d2001-07-17 01:12:36 +00001783static struct obj_symbol *
1784obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001785{
1786 struct obj_symbol *sym;
1787 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1788
1789 for (sym = f->symtab[hash]; sym; sym = sym->next)
1790 if (f->symbol_cmp(sym->name, name) == 0)
1791 return sym;
1792
1793 return NULL;
1794}
1795
Eric Andersen044228d2001-07-17 01:12:36 +00001796static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001797 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1798{
1799 if (sym) {
1800 if (sym->secidx >= SHN_LORESERVE)
1801 return sym->value;
1802
1803 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1804 } else {
1805 /* As a special case, a NULL sym has value zero. */
1806 return 0;
1807 }
1808}
1809
Eric Andersen044228d2001-07-17 01:12:36 +00001810static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001811{
1812 int i, n = f->header.e_shnum;
1813
1814 for (i = 0; i < n; ++i)
1815 if (strcmp(f->sections[i]->name, name) == 0)
1816 return f->sections[i];
1817
1818 return NULL;
1819}
1820
1821static int obj_load_order_prio(struct obj_section *a)
1822{
1823 unsigned long af, ac;
1824
1825 af = a->header.sh_flags;
1826
1827 ac = 0;
1828 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1829 strcmp(a->name + 5, ".init"))
1830 ac |= 32;
1831 if (af & SHF_ALLOC)
1832 ac |= 16;
1833 if (!(af & SHF_WRITE))
1834 ac |= 8;
1835 if (af & SHF_EXECINSTR)
1836 ac |= 4;
1837 if (a->header.sh_type != SHT_NOBITS)
1838 ac |= 2;
1839
1840 return ac;
1841}
1842
Eric Andersen044228d2001-07-17 01:12:36 +00001843static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001844obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1845{
1846 struct obj_section **p;
1847 int prio = obj_load_order_prio(sec);
1848 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1849 if (obj_load_order_prio(*p) < prio)
1850 break;
1851 sec->load_next = *p;
1852 *p = sec;
1853}
1854
Eric Andersen044228d2001-07-17 01:12:36 +00001855static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001856 const char *name,
1857 unsigned long align,
1858 unsigned long size)
1859{
1860 int newidx = f->header.e_shnum++;
1861 struct obj_section *sec;
1862
1863 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1864 f->sections[newidx] = sec = arch_new_section();
1865
1866 memset(sec, 0, sizeof(*sec));
1867 sec->header.sh_type = SHT_PROGBITS;
1868 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1869 sec->header.sh_size = size;
1870 sec->header.sh_addralign = align;
1871 sec->name = name;
1872 sec->idx = newidx;
1873 if (size)
1874 sec->contents = xmalloc(size);
1875
1876 obj_insert_section_load_order(f, sec);
1877
1878 return sec;
1879}
1880
Eric Andersen044228d2001-07-17 01:12:36 +00001881static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001882 const char *name,
1883 unsigned long align,
1884 unsigned long size)
1885{
1886 int newidx = f->header.e_shnum++;
1887 struct obj_section *sec;
1888
1889 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1890 f->sections[newidx] = sec = arch_new_section();
1891
1892 memset(sec, 0, sizeof(*sec));
1893 sec->header.sh_type = SHT_PROGBITS;
1894 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1895 sec->header.sh_size = size;
1896 sec->header.sh_addralign = align;
1897 sec->name = name;
1898 sec->idx = newidx;
1899 if (size)
1900 sec->contents = xmalloc(size);
1901
1902 sec->load_next = f->load_order;
1903 f->load_order = sec;
1904 if (f->load_order_search_start == &f->load_order)
1905 f->load_order_search_start = &sec->load_next;
1906
1907 return sec;
1908}
1909
Eric Andersen044228d2001-07-17 01:12:36 +00001910static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001911{
1912 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001913 if (more) {
1914 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1915 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001916 return sec->contents + oldsize;
1917}
1918
1919
Eric Andersen9f16d612000-06-12 23:11:16 +00001920/* Conditionally add the symbols from the given symbol set to the
1921 new module. */
1922
1923static int
1924add_symbols_from(
1925 struct obj_file *f,
1926 int idx, struct new_module_symbol *syms, size_t nsyms)
1927{
1928 struct new_module_symbol *s;
1929 size_t i;
1930 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001931#ifdef SYMBOL_PREFIX
1932 char *name_buf = 0;
1933 size_t name_alloced_size = 0;
1934#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001935#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
1936 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00001937
Glenn L McGrath759515c2003-08-30 06:00:33 +00001938 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001939#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001940 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001941 /* Only add symbols that are already marked external.
1942 If we override locals we may cause problems for
1943 argument initialization. We will also create a false
1944 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001945 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001946 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00001947
Glenn L McGrath759515c2003-08-30 06:00:33 +00001948 /* GPL licensed modules can use symbols exported with
1949 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
1950 * exported names. Non-GPL modules never see any GPLONLY_
1951 * symbols so they cannot fudge it by adding the prefix on
1952 * their references.
1953 */
1954 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001955#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00001956 if (gpl)
1957 ((char *)s->name) += 8;
1958 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001959#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00001960 continue;
1961 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001962 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00001963
Miles Baderae28b042002-04-01 09:34:25 +00001964#ifdef SYMBOL_PREFIX
1965 /* Prepend SYMBOL_PREFIX to the symbol's name (the
1966 kernel exports `C names', but module object files
1967 reference `linker names'). */
1968 size_t extra = sizeof SYMBOL_PREFIX;
1969 size_t name_size = strlen (name) + extra;
1970 if (name_size > name_alloced_size) {
1971 name_alloced_size = name_size * 2;
1972 name_buf = alloca (name_alloced_size);
1973 }
1974 strcpy (name_buf, SYMBOL_PREFIX);
1975 strcpy (name_buf + extra - 1, name);
1976 name = name_buf;
1977#endif /* SYMBOL_PREFIX */
1978
1979 sym = obj_find_symbol(f, name);
1980 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
1981#ifdef SYMBOL_PREFIX
1982 /* Put NAME_BUF into more permanent storage. */
1983 name = xmalloc (name_size);
1984 strcpy (name, name_buf);
1985#endif
1986 sym = obj_add_symbol(f, name, -1,
1987 ELFW(ST_INFO) (STB_GLOBAL,
1988 STT_NOTYPE),
1989 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00001990 /* Did our symbol just get installed? If so, mark the
1991 module as "used". */
1992 if (sym->secidx == idx)
1993 used = 1;
1994 }
1995 }
1996
1997 return used;
1998}
1999
2000static void add_kernel_symbols(struct obj_file *f)
2001{
2002 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002003 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002004
2005 /* Add module symbols first. */
2006
2007 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2008 if (m->nsyms
2009 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2010 m->nsyms)) m->used = 1, ++nused;
2011
2012 n_ext_modules_used = nused;
2013
2014 /* And finally the symbols from the kernel proper. */
2015
2016 if (nksyms)
2017 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2018}
2019
2020static char *get_modinfo_value(struct obj_file *f, const char *key)
2021{
2022 struct obj_section *sec;
2023 char *p, *v, *n, *ep;
2024 size_t klen = strlen(key);
2025
2026 sec = obj_find_section(f, ".modinfo");
2027 if (sec == NULL)
2028 return NULL;
2029 p = sec->contents;
2030 ep = p + sec->header.sh_size;
2031 while (p < ep) {
2032 v = strchr(p, '=');
2033 n = strchr(p, '\0');
2034 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002035 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002036 return v + 1;
2037 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002038 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002039 return n;
2040 }
2041 p = n + 1;
2042 }
2043
2044 return NULL;
2045}
2046
2047
2048/*======================================================================*/
2049/* Functions relating to module loading in pre 2.1 kernels. */
2050
2051static int
2052old_process_module_arguments(struct obj_file *f, int argc, char **argv)
2053{
2054 while (argc > 0) {
2055 char *p, *q;
2056 struct obj_symbol *sym;
2057 int *loc;
2058
2059 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002060 if ((q = strchr(p, '=')) == NULL) {
2061 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002062 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002063 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002064 *q++ = '\0';
2065
2066 sym = obj_find_symbol(f, p);
2067
2068 /* Also check that the parameter was not resolved from the kernel. */
2069 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002070 bb_error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002071 return 0;
2072 }
2073
2074 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
2075
2076 /* Do C quoting if we begin with a ". */
2077 if (*q == '"') {
2078 char *r, *str;
2079
2080 str = alloca(strlen(q));
2081 for (r = str, q++; *q != '"'; ++q, ++r) {
2082 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002083 bb_error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002084 return 0;
2085 } else if (*q == '\\')
2086 switch (*++q) {
2087 case 'a':
2088 *r = '\a';
2089 break;
2090 case 'b':
2091 *r = '\b';
2092 break;
2093 case 'e':
2094 *r = '\033';
2095 break;
2096 case 'f':
2097 *r = '\f';
2098 break;
2099 case 'n':
2100 *r = '\n';
2101 break;
2102 case 'r':
2103 *r = '\r';
2104 break;
2105 case 't':
2106 *r = '\t';
2107 break;
2108
2109 case '0':
2110 case '1':
2111 case '2':
2112 case '3':
2113 case '4':
2114 case '5':
2115 case '6':
2116 case '7':
2117 {
2118 int c = *q - '0';
2119 if (q[1] >= '0' && q[1] <= '7') {
2120 c = (c * 8) + *++q - '0';
2121 if (q[1] >= '0' && q[1] <= '7')
2122 c = (c * 8) + *++q - '0';
2123 }
2124 *r = c;
2125 }
2126 break;
2127
2128 default:
2129 *r = *q;
2130 break;
2131 } else
2132 *r = *q;
2133 }
2134 *r = '\0';
2135 obj_string_patch(f, sym->secidx, sym->value, str);
2136 } else if (*q >= '0' && *q <= '9') {
2137 do
2138 *loc++ = strtoul(q, &q, 0);
2139 while (*q++ == ',');
2140 } else {
2141 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00002142 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002143 char *r; /* To search for commas */
2144
2145 /* Break the string with comas */
2146 while ((r = strchr(q, ',')) != (char *) NULL) {
2147 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00002148 obj_string_patch(f, sym->secidx, myloc - contents, q);
2149 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00002150 q = r;
2151 }
2152
2153 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00002154 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00002155 }
2156
2157 argc--, argv++;
2158 }
2159
2160 return 1;
2161}
2162
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002163#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002164static int old_is_module_checksummed(struct obj_file *f)
2165{
2166 return obj_find_symbol(f, "Using_Versions") != NULL;
2167}
2168/* Get the module's kernel version in the canonical integer form. */
2169
2170static int
2171old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2172{
2173 struct obj_symbol *sym;
2174 char *p, *q;
2175 int a, b, c;
2176
2177 sym = obj_find_symbol(f, "kernel_version");
2178 if (sym == NULL)
2179 return -1;
2180
2181 p = f->sections[sym->secidx]->contents + sym->value;
Eric Andersen2d342152002-06-18 05:16:25 +00002182 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002183
2184 a = strtoul(p, &p, 10);
2185 if (*p != '.')
2186 return -1;
2187 b = strtoul(p + 1, &p, 10);
2188 if (*p != '.')
2189 return -1;
2190 c = strtoul(p + 1, &q, 10);
2191 if (p + 1 == q)
2192 return -1;
2193
2194 return a << 16 | b << 8 | c;
2195}
2196
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002197#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002198
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002199#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002200
2201/* Fetch all the symbols and divvy them up as appropriate for the modules. */
2202
Eric Andersen8c185f92000-09-22 00:38:07 +00002203static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002204{
2205 struct old_kernel_sym *ks, *k;
2206 struct new_module_symbol *s;
2207 struct external_module *mod;
2208 int nks, nms, nmod, i;
2209
2210 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00002211 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002212 if (nks)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002213 bb_perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002214 else
Manuel Novoa III cad53642003-03-19 09:13:01 +00002215 bb_error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00002216 return 0;
2217 }
2218
2219 ks = k = xmalloc(nks * sizeof(*ks));
2220
2221 if (get_kernel_syms(ks) != nks) {
2222 perror("inconsistency with get_kernel_syms -- is someone else "
2223 "playing with modules?");
2224 free(ks);
2225 return 0;
2226 }
2227
2228 /* Collect the module information. */
2229
2230 mod = NULL;
2231 nmod = -1;
2232
2233 while (k->name[0] == '#' && k->name[1]) {
2234 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00002235
2236 /* Find out how many symbols this module has. */
2237 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
2238 continue;
2239 nms = k2 - k - 1;
2240
2241 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
2242 mod[nmod].name = k->name + 1;
2243 mod[nmod].addr = k->value;
2244 mod[nmod].used = 0;
2245 mod[nmod].nsyms = nms;
2246 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2247
2248 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
2249 s->name = (unsigned long) k->name;
2250 s->value = k->value;
2251 }
2252
2253 k = k2;
2254 }
2255
2256 ext_modules = mod;
2257 n_ext_modules = nmod + 1;
2258
2259 /* Now collect the symbols for the kernel proper. */
2260
2261 if (k->name[0] == '#')
2262 ++k;
2263
2264 nksyms = nms = nks - (k - ks);
2265 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2266
2267 for (i = 0; i < nms; ++i, ++s, ++k) {
2268 s->name = (unsigned long) k->name;
2269 s->value = k->value;
2270 }
2271
2272 return 1;
2273}
2274
2275/* Return the kernel symbol checksum version, or zero if not used. */
2276
2277static int old_is_kernel_checksummed(void)
2278{
2279 /* Using_Versions is the first symbol. */
2280 if (nksyms > 0
2281 && strcmp((char *) ksyms[0].name,
2282 "Using_Versions") == 0) return ksyms[0].value;
2283 else
2284 return 0;
2285}
2286
2287
2288static int old_create_mod_use_count(struct obj_file *f)
2289{
2290 struct obj_section *sec;
2291
2292 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
2293 sizeof(long));
2294
2295 obj_add_symbol(f, "mod_use_count_", -1,
2296 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2297 sizeof(long));
2298
2299 return 1;
2300}
2301
2302static int
2303old_init_module(const char *m_name, struct obj_file *f,
2304 unsigned long m_size)
2305{
2306 char *image;
2307 struct old_mod_routines routines;
2308 struct old_symbol_table *symtab;
2309 int ret;
2310
2311 /* Create the symbol table */
2312 {
2313 int nsyms = 0, strsize = 0, total;
2314
2315 /* Size things first... */
2316 if (flag_export) {
2317 int i;
2318 for (i = 0; i < HASH_BUCKETS; ++i) {
2319 struct obj_symbol *sym;
2320 for (sym = f->symtab[i]; sym; sym = sym->next)
2321 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2322 && sym->secidx <= SHN_HIRESERVE)
2323 {
2324 sym->ksymidx = nsyms++;
2325 strsize += strlen(sym->name) + 1;
2326 }
2327 }
2328 }
2329
2330 total = (sizeof(struct old_symbol_table)
2331 + nsyms * sizeof(struct old_module_symbol)
2332 + n_ext_modules_used * sizeof(struct old_module_ref)
2333 + strsize);
2334 symtab = xmalloc(total);
2335 symtab->size = total;
2336 symtab->n_symbols = nsyms;
2337 symtab->n_refs = n_ext_modules_used;
2338
2339 if (flag_export && nsyms) {
2340 struct old_module_symbol *ksym;
2341 char *str;
2342 int i;
2343
2344 ksym = symtab->symbol;
2345 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
2346 + n_ext_modules_used * sizeof(struct old_module_ref));
2347
2348 for (i = 0; i < HASH_BUCKETS; ++i) {
2349 struct obj_symbol *sym;
2350 for (sym = f->symtab[i]; sym; sym = sym->next)
2351 if (sym->ksymidx >= 0) {
2352 ksym->addr = obj_symbol_final_value(f, sym);
2353 ksym->name =
2354 (unsigned long) str - (unsigned long) symtab;
2355
Matt Kraai70a78552001-01-04 02:00:17 +00002356 strcpy(str, sym->name);
2357 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002358 ksym++;
2359 }
2360 }
2361 }
2362
2363 if (n_ext_modules_used) {
2364 struct old_module_ref *ref;
2365 int i;
2366
2367 ref = (struct old_module_ref *)
2368 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2369
2370 for (i = 0; i < n_ext_modules; ++i)
2371 if (ext_modules[i].used)
2372 ref++->module = ext_modules[i].addr;
2373 }
2374 }
2375
2376 /* Fill in routines. */
2377
2378 routines.init =
Miles Baderae28b042002-04-01 09:34:25 +00002379 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002380 routines.cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002381 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002382
2383 /* Whew! All of the initialization is complete. Collect the final
2384 module image and give it to the kernel. */
2385
2386 image = xmalloc(m_size);
2387 obj_create_image(f, image);
2388
2389 /* image holds the complete relocated module, accounting correctly for
2390 mod_use_count. However the old module kernel support assume that
2391 it is receiving something which does not contain mod_use_count. */
2392 ret = old_sys_init_module(m_name, image + sizeof(long),
2393 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2394 : 0), &routines, symtab);
2395 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002396 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002397
2398 free(image);
2399 free(symtab);
2400
2401 return ret == 0;
2402}
2403
2404#else
2405
2406#define old_create_mod_use_count(x) TRUE
2407#define old_init_module(x, y, z) TRUE
2408
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002409#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002410
2411
2412
2413/*======================================================================*/
2414/* Functions relating to module loading after 2.1.18. */
2415
2416static int
2417new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2418{
2419 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002420 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002421 struct obj_symbol *sym;
2422 char *contents, *loc;
2423 int min, max, n;
2424
2425 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002426 if ((q = strchr(p, '=')) == NULL) {
2427 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002428 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002429 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002430
2431 key = alloca(q - p + 6);
2432 memcpy(key, "parm_", 5);
2433 memcpy(key + 5, p, q - p);
2434 key[q - p + 5] = 0;
2435
2436 p = get_modinfo_value(f, key);
2437 key += 5;
2438 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002439 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002440 return 0;
2441 }
2442
Miles Baderae28b042002-04-01 09:34:25 +00002443#ifdef SYMBOL_PREFIX
2444 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2445 strcpy (sym_name, SYMBOL_PREFIX);
2446 strcat (sym_name, key);
2447#else
2448 sym_name = key;
2449#endif
2450 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002451
2452 /* Also check that the parameter was not resolved from the kernel. */
2453 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002454 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002455 return 0;
2456 }
2457
2458 if (isdigit(*p)) {
2459 min = strtoul(p, &p, 10);
2460 if (*p == '-')
2461 max = strtoul(p + 1, &p, 10);
2462 else
2463 max = min;
2464 } else
2465 min = max = 1;
2466
2467 contents = f->sections[sym->secidx]->contents;
2468 loc = contents + sym->value;
2469 n = (*++q != '\0');
2470
2471 while (1) {
2472 if ((*p == 's') || (*p == 'c')) {
2473 char *str;
2474
2475 /* Do C quoting if we begin with a ", else slurp the lot. */
2476 if (*q == '"') {
2477 char *r;
2478
2479 str = alloca(strlen(q));
2480 for (r = str, q++; *q != '"'; ++q, ++r) {
2481 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002482 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002483 key);
2484 return 0;
2485 } else if (*q == '\\')
2486 switch (*++q) {
2487 case 'a':
2488 *r = '\a';
2489 break;
2490 case 'b':
2491 *r = '\b';
2492 break;
2493 case 'e':
2494 *r = '\033';
2495 break;
2496 case 'f':
2497 *r = '\f';
2498 break;
2499 case 'n':
2500 *r = '\n';
2501 break;
2502 case 'r':
2503 *r = '\r';
2504 break;
2505 case 't':
2506 *r = '\t';
2507 break;
2508
2509 case '0':
2510 case '1':
2511 case '2':
2512 case '3':
2513 case '4':
2514 case '5':
2515 case '6':
2516 case '7':
2517 {
2518 int c = *q - '0';
2519 if (q[1] >= '0' && q[1] <= '7') {
2520 c = (c * 8) + *++q - '0';
2521 if (q[1] >= '0' && q[1] <= '7')
2522 c = (c * 8) + *++q - '0';
2523 }
2524 *r = c;
2525 }
2526 break;
2527
2528 default:
2529 *r = *q;
2530 break;
2531 } else
2532 *r = *q;
2533 }
2534 *r = '\0';
2535 ++q;
2536 } else {
2537 char *r;
2538
2539 /* In this case, the string is not quoted. We will break
2540 it using the coma (like for ints). If the user wants to
2541 include comas in a string, he just has to quote it */
2542
2543 /* Search the next coma */
2544 r = strchr(q, ',');
2545
2546 /* Found ? */
2547 if (r != (char *) NULL) {
2548 /* Recopy the current field */
2549 str = alloca(r - q + 1);
2550 memcpy(str, q, r - q);
2551
2552 /* I don't know if it is usefull, as the previous case
2553 doesn't null terminate the string ??? */
2554 str[r - q] = '\0';
2555
2556 /* Keep next fields */
2557 q = r;
2558 } else {
2559 /* last string */
2560 str = q;
2561 q = "";
2562 }
2563 }
2564
2565 if (*p == 's') {
2566 /* Normal string */
2567 obj_string_patch(f, sym->secidx, loc - contents, str);
2568 loc += tgt_sizeof_char_p;
2569 } else {
2570 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002571 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002572
2573 /* Get the size of each member */
2574 /* Probably we should do that outside the loop ? */
2575 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002576 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002577 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002578 return 0;
2579 }
2580 charssize = strtoul(p + 1, (char **) NULL, 10);
2581
2582 /* Check length */
2583 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002584 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002585 charssize - 1);
2586 return 0;
2587 }
2588
2589 /* Copy to location */
2590 strcpy((char *) loc, str);
2591 loc += charssize;
2592 }
2593 } else {
2594 long v = strtoul(q, &q, 0);
2595 switch (*p) {
2596 case 'b':
2597 *loc++ = v;
2598 break;
2599 case 'h':
2600 *(short *) loc = v;
2601 loc += tgt_sizeof_short;
2602 break;
2603 case 'i':
2604 *(int *) loc = v;
2605 loc += tgt_sizeof_int;
2606 break;
2607 case 'l':
2608 *(long *) loc = v;
2609 loc += tgt_sizeof_long;
2610 break;
2611
2612 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002613 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002614 return 0;
2615 }
2616 }
2617
2618 retry_end_of_value:
2619 switch (*q) {
2620 case '\0':
2621 goto end_of_arg;
2622
2623 case ' ':
2624 case '\t':
2625 case '\n':
2626 case '\r':
2627 ++q;
2628 goto retry_end_of_value;
2629
2630 case ',':
2631 if (++n > max) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002632 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002633 return 0;
2634 }
2635 ++q;
2636 break;
2637
2638 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002639 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002640 return 0;
2641 }
2642 }
2643
2644 end_of_arg:
2645 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002646 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002647 return 0;
2648 }
2649
2650 argc--, argv++;
2651 }
2652
2653 return 1;
2654}
2655
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002656#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002657static int new_is_module_checksummed(struct obj_file *f)
2658{
2659 const char *p = get_modinfo_value(f, "using_checksums");
2660 if (p)
2661 return atoi(p);
2662 else
2663 return 0;
2664}
2665
2666/* Get the module's kernel version in the canonical integer form. */
2667
2668static int
2669new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2670{
2671 char *p, *q;
2672 int a, b, c;
2673
2674 p = get_modinfo_value(f, "kernel_version");
2675 if (p == NULL)
2676 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002677 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002678
2679 a = strtoul(p, &p, 10);
2680 if (*p != '.')
2681 return -1;
2682 b = strtoul(p + 1, &p, 10);
2683 if (*p != '.')
2684 return -1;
2685 c = strtoul(p + 1, &q, 10);
2686 if (p + 1 == q)
2687 return -1;
2688
2689 return a << 16 | b << 8 | c;
2690}
2691
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002692#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002693
2694
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002695#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002696
2697/* Fetch the loaded modules, and all currently exported symbols. */
2698
2699static int new_get_kernel_symbols(void)
2700{
2701 char *module_names, *mn;
2702 struct external_module *modules, *m;
2703 struct new_module_symbol *syms, *s;
2704 size_t ret, bufsize, nmod, nsyms, i, j;
2705
2706 /* Collect the loaded modules. */
2707
2708 module_names = xmalloc(bufsize = 256);
2709 retry_modules_load:
2710 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002711 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002712 module_names = xrealloc(module_names, bufsize = ret);
2713 goto retry_modules_load;
2714 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002715 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 return 0;
2717 }
2718
2719 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002720
2721 /* Collect the modules' symbols. */
2722
Mark Whitley94fd4802001-03-12 23:08:34 +00002723 if (nmod){
2724 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2725 memset(modules, 0, nmod * sizeof(*modules));
2726 for (i = 0, mn = module_names, m = modules;
2727 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2728 struct new_module_info info;
2729
2730 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2731 if (errno == ENOENT) {
2732 /* The module was removed out from underneath us. */
2733 continue;
2734 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002735 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002736 return 0;
2737 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002738
2739 syms = xmalloc(bufsize = 1024);
2740 retry_mod_sym_load:
2741 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2742 switch (errno) {
2743 case ENOSPC:
2744 syms = xrealloc(syms, bufsize = ret);
2745 goto retry_mod_sym_load;
2746 case ENOENT:
2747 /* The module was removed out from underneath us. */
2748 continue;
2749 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002750 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002751 return 0;
2752 }
2753 }
2754 nsyms = ret;
2755
2756 m->name = mn;
2757 m->addr = info.addr;
2758 m->nsyms = nsyms;
2759 m->syms = syms;
2760
2761 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2762 s->name += (unsigned long) syms;
2763 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002764 }
2765 }
2766
2767 /* Collect the kernel's symbols. */
2768
2769 syms = xmalloc(bufsize = 16 * 1024);
2770 retry_kern_sym_load:
2771 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002772 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002773 syms = xrealloc(syms, bufsize = ret);
2774 goto retry_kern_sym_load;
2775 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002776 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002777 return 0;
2778 }
2779 nksyms = nsyms = ret;
2780 ksyms = syms;
2781
2782 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2783 s->name += (unsigned long) syms;
2784 }
2785 return 1;
2786}
2787
2788
2789/* Return the kernel symbol checksum version, or zero if not used. */
2790
2791static int new_is_kernel_checksummed(void)
2792{
2793 struct new_module_symbol *s;
2794 size_t i;
2795
2796 /* Using_Versions is not the first symbol, but it should be in there. */
2797
2798 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2799 if (strcmp((char *) s->name, "Using_Versions") == 0)
2800 return s->value;
2801
2802 return 0;
2803}
2804
2805
2806static int new_create_this_module(struct obj_file *f, const char *m_name)
2807{
2808 struct obj_section *sec;
2809
2810 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2811 sizeof(struct new_module));
2812 memset(sec->contents, 0, sizeof(struct new_module));
2813
Miles Baderae28b042002-04-01 09:34:25 +00002814 obj_add_symbol(f, SPFX "__this_module", -1,
2815 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2816 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002817
2818 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2819 m_name);
2820
2821 return 1;
2822}
2823
Eric Andersen889dd202003-01-23 04:48:34 +00002824#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2825/* add an entry to the __ksymtab section, creating it if necessary */
2826static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2827{
2828 struct obj_section *sec;
2829 ElfW(Addr) ofs;
2830
2831 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2832 * If __ksymtab is defined but not marked alloc, x out the first character
2833 * (no obj_delete routine) and create a new __ksymtab with the correct
2834 * characteristics.
2835 */
2836 sec = obj_find_section(f, "__ksymtab");
2837 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2838 *((char *)(sec->name)) = 'x'; /* override const */
2839 sec = NULL;
2840 }
2841 if (!sec)
2842 sec = obj_create_alloced_section(f, "__ksymtab",
2843 tgt_sizeof_void_p, 0);
2844 if (!sec)
2845 return;
2846 sec->header.sh_flags |= SHF_ALLOC;
2847 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
2848 be byte-aligned */
2849 ofs = sec->header.sh_size;
2850 obj_symbol_patch(f, sec->idx, ofs, sym);
2851 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2852 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2853}
2854#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002855
2856static int new_create_module_ksymtab(struct obj_file *f)
2857{
2858 struct obj_section *sec;
2859 int i;
2860
2861 /* We must always add the module references. */
2862
2863 if (n_ext_modules_used) {
2864 struct new_module_ref *dep;
2865 struct obj_symbol *tm;
2866
2867 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2868 (sizeof(struct new_module_ref)
2869 * n_ext_modules_used));
2870 if (!sec)
2871 return 0;
2872
Miles Baderae28b042002-04-01 09:34:25 +00002873 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002874 dep = (struct new_module_ref *) sec->contents;
2875 for (i = 0; i < n_ext_modules; ++i)
2876 if (ext_modules[i].used) {
2877 dep->dep = ext_modules[i].addr;
2878 obj_symbol_patch(f, sec->idx,
2879 (char *) &dep->ref - sec->contents, tm);
2880 dep->next_ref = 0;
2881 ++dep;
2882 }
2883 }
2884
2885 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2886 size_t nsyms;
2887 int *loaded;
2888
2889 sec =
2890 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2891 0);
2892
2893 /* We don't want to export symbols residing in sections that
2894 aren't loaded. There are a number of these created so that
2895 we make sure certain module options don't appear twice. */
2896
2897 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2898 while (--i >= 0)
2899 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2900
2901 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2902 struct obj_symbol *sym;
2903 for (sym = f->symtab[i]; sym; sym = sym->next)
2904 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2905 && sym->secidx <= SHN_HIRESERVE
2906 && (sym->secidx >= SHN_LORESERVE
2907 || loaded[sym->secidx])) {
2908 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2909
2910 obj_symbol_patch(f, sec->idx, ofs, sym);
2911 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2912 sym->name);
2913
2914 nsyms++;
2915 }
2916 }
2917
2918 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2919 }
2920
2921 return 1;
2922}
2923
2924
2925static int
2926new_init_module(const char *m_name, struct obj_file *f,
2927 unsigned long m_size)
2928{
2929 struct new_module *module;
2930 struct obj_section *sec;
2931 void *image;
2932 int ret;
2933 tgt_long m_addr;
2934
2935 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002936 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002937 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002938 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002939 module = (struct new_module *) sec->contents;
2940 m_addr = sec->header.sh_addr;
2941
2942 module->size_of_struct = sizeof(*module);
2943 module->size = m_size;
2944 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2945
2946 sec = obj_find_section(f, "__ksymtab");
2947 if (sec && sec->header.sh_size) {
2948 module->syms = sec->header.sh_addr;
2949 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2950 }
2951
2952 if (n_ext_modules_used) {
2953 sec = obj_find_section(f, ".kmodtab");
2954 module->deps = sec->header.sh_addr;
2955 module->ndeps = n_ext_modules_used;
2956 }
2957
2958 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002959 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002960 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002961 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002962
2963 sec = obj_find_section(f, "__ex_table");
2964 if (sec) {
2965 module->ex_table_start = sec->header.sh_addr;
2966 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2967 }
2968
2969 sec = obj_find_section(f, ".text.init");
2970 if (sec) {
2971 module->runsize = sec->header.sh_addr - m_addr;
2972 }
2973 sec = obj_find_section(f, ".data.init");
2974 if (sec) {
2975 if (!module->runsize ||
2976 module->runsize > sec->header.sh_addr - m_addr)
2977 module->runsize = sec->header.sh_addr - m_addr;
2978 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002979 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2980 if (sec && sec->header.sh_size) {
2981 module->archdata_start = (void*)sec->header.sh_addr;
2982 module->archdata_end = module->archdata_start + sec->header.sh_size;
2983 }
2984 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2985 if (sec && sec->header.sh_size) {
2986 module->kallsyms_start = (void*)sec->header.sh_addr;
2987 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2988 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002989
2990 if (!arch_init_module(f, module))
2991 return 0;
2992
2993 /* Whew! All of the initialization is complete. Collect the final
2994 module image and give it to the kernel. */
2995
2996 image = xmalloc(m_size);
2997 obj_create_image(f, image);
2998
Eric Andersen64c8b172001-04-05 07:33:10 +00002999 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00003000 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003001 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003002
3003 free(image);
3004
3005 return ret == 0;
3006}
3007
3008#else
3009
3010#define new_init_module(x, y, z) TRUE
3011#define new_create_this_module(x, y) 0
Eric Andersen889dd202003-01-23 04:48:34 +00003012#define new_add_ksymtab(x, y) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003013#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00003014#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003015
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003016#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003017
3018
3019/*======================================================================*/
3020
Eric Andersen044228d2001-07-17 01:12:36 +00003021static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003022obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3023 const char *string)
3024{
3025 struct obj_string_patch *p;
3026 struct obj_section *strsec;
3027 size_t len = strlen(string) + 1;
3028 char *loc;
3029
3030 p = xmalloc(sizeof(*p));
3031 p->next = f->string_patches;
3032 p->reloc_secidx = secidx;
3033 p->reloc_offset = offset;
3034 f->string_patches = p;
3035
3036 strsec = obj_find_section(f, ".kstrtab");
3037 if (strsec == NULL) {
3038 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3039 p->string_offset = 0;
3040 loc = strsec->contents;
3041 } else {
3042 p->string_offset = strsec->header.sh_size;
3043 loc = obj_extend_section(strsec, len);
3044 }
3045 memcpy(loc, string, len);
3046
3047 return 1;
3048}
3049
Eric Andersen6d139642001-12-29 04:15:13 +00003050#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00003051static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003052obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3053 struct obj_symbol *sym)
3054{
3055 struct obj_symbol_patch *p;
3056
3057 p = xmalloc(sizeof(*p));
3058 p->next = f->symbol_patches;
3059 p->reloc_secidx = secidx;
3060 p->reloc_offset = offset;
3061 p->sym = sym;
3062 f->symbol_patches = p;
3063
3064 return 1;
3065}
Eric Andersen6d139642001-12-29 04:15:13 +00003066#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003067
Eric Andersen044228d2001-07-17 01:12:36 +00003068static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003069{
3070 unsigned long i;
3071 int ret = 1;
3072
3073 for (i = 0; i < HASH_BUCKETS; ++i) {
3074 struct obj_symbol *sym;
3075 for (sym = f->symtab[i]; sym; sym = sym->next)
3076 if (sym->secidx == SHN_UNDEF) {
3077 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
3078 sym->secidx = SHN_ABS;
3079 sym->value = 0;
3080 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003081 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003082 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003083 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003084 ret = 0;
3085 }
3086 }
3087 }
3088
3089 return ret;
3090}
3091
Eric Andersen044228d2001-07-17 01:12:36 +00003092static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003093{
3094 struct common_entry {
3095 struct common_entry *next;
3096 struct obj_symbol *sym;
3097 } *common_head = NULL;
3098
3099 unsigned long i;
3100
3101 for (i = 0; i < HASH_BUCKETS; ++i) {
3102 struct obj_symbol *sym;
3103 for (sym = f->symtab[i]; sym; sym = sym->next)
3104 if (sym->secidx == SHN_COMMON) {
3105 /* Collect all COMMON symbols and sort them by size so as to
3106 minimize space wasted by alignment requirements. */
3107 {
3108 struct common_entry **p, *n;
3109 for (p = &common_head; *p; p = &(*p)->next)
3110 if (sym->size <= (*p)->sym->size)
3111 break;
3112
3113 n = alloca(sizeof(*n));
3114 n->next = *p;
3115 n->sym = sym;
3116 *p = n;
3117 }
3118 }
3119 }
3120
3121 for (i = 1; i < f->local_symtab_size; ++i) {
3122 struct obj_symbol *sym = f->local_symtab[i];
3123 if (sym && sym->secidx == SHN_COMMON) {
3124 struct common_entry **p, *n;
3125 for (p = &common_head; *p; p = &(*p)->next)
3126 if (sym == (*p)->sym)
3127 break;
3128 else if (sym->size < (*p)->sym->size) {
3129 n = alloca(sizeof(*n));
3130 n->next = *p;
3131 n->sym = sym;
3132 *p = n;
3133 break;
3134 }
3135 }
3136 }
3137
3138 if (common_head) {
3139 /* Find the bss section. */
3140 for (i = 0; i < f->header.e_shnum; ++i)
3141 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3142 break;
3143
3144 /* If for some reason there hadn't been one, create one. */
3145 if (i == f->header.e_shnum) {
3146 struct obj_section *sec;
3147
3148 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3149 f->sections[i] = sec = arch_new_section();
3150 f->header.e_shnum = i + 1;
3151
3152 memset(sec, 0, sizeof(*sec));
3153 sec->header.sh_type = SHT_PROGBITS;
3154 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3155 sec->name = ".bss";
3156 sec->idx = i;
3157 }
3158
3159 /* Allocate the COMMONS. */
3160 {
3161 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3162 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3163 struct common_entry *c;
3164
3165 for (c = common_head; c; c = c->next) {
3166 ElfW(Addr) align = c->sym->value;
3167
3168 if (align > max_align)
3169 max_align = align;
3170 if (bss_size & (align - 1))
3171 bss_size = (bss_size | (align - 1)) + 1;
3172
3173 c->sym->secidx = i;
3174 c->sym->value = bss_size;
3175
3176 bss_size += c->sym->size;
3177 }
3178
3179 f->sections[i]->header.sh_size = bss_size;
3180 f->sections[i]->header.sh_addralign = max_align;
3181 }
3182 }
3183
3184 /* For the sake of patch relocation and parameter initialization,
3185 allocate zeroed data for NOBITS sections now. Note that after
3186 this we cannot assume NOBITS are really empty. */
3187 for (i = 0; i < f->header.e_shnum; ++i) {
3188 struct obj_section *s = f->sections[i];
3189 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003190 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003191 s->contents = memset(xmalloc(s->header.sh_size),
3192 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003193 else
3194 s->contents = NULL;
3195
Eric Andersen9f16d612000-06-12 23:11:16 +00003196 s->header.sh_type = SHT_PROGBITS;
3197 }
3198 }
3199}
3200
Eric Andersen044228d2001-07-17 01:12:36 +00003201static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003202{
3203 unsigned long dot = 0;
3204 struct obj_section *sec;
3205
3206 /* Finalize the positions of the sections relative to one another. */
3207
3208 for (sec = f->load_order; sec; sec = sec->load_next) {
3209 ElfW(Addr) align;
3210
3211 align = sec->header.sh_addralign;
3212 if (align && (dot & (align - 1)))
3213 dot = (dot | (align - 1)) + 1;
3214
3215 sec->header.sh_addr = dot;
3216 dot += sec->header.sh_size;
3217 }
3218
3219 return dot;
3220}
3221
Eric Andersen044228d2001-07-17 01:12:36 +00003222static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003223{
3224 int i, n = f->header.e_shnum;
3225 int ret = 1;
3226
3227 /* Finalize the addresses of the sections. */
3228
3229 f->baseaddr = base;
3230 for (i = 0; i < n; ++i)
3231 f->sections[i]->header.sh_addr += base;
3232
3233 /* And iterate over all of the relocations. */
3234
3235 for (i = 0; i < n; ++i) {
3236 struct obj_section *relsec, *symsec, *targsec, *strsec;
3237 ElfW(RelM) * rel, *relend;
3238 ElfW(Sym) * symtab;
3239 const char *strtab;
3240
3241 relsec = f->sections[i];
3242 if (relsec->header.sh_type != SHT_RELM)
3243 continue;
3244
3245 symsec = f->sections[relsec->header.sh_link];
3246 targsec = f->sections[relsec->header.sh_info];
3247 strsec = f->sections[symsec->header.sh_link];
3248
3249 rel = (ElfW(RelM) *) relsec->contents;
3250 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3251 symtab = (ElfW(Sym) *) symsec->contents;
3252 strtab = (const char *) strsec->contents;
3253
3254 for (; rel < relend; ++rel) {
3255 ElfW(Addr) value = 0;
3256 struct obj_symbol *intsym = NULL;
3257 unsigned long symndx;
3258 ElfW(Sym) * extsym = 0;
3259 const char *errmsg;
3260
3261 /* Attempt to find a value to use for this relocation. */
3262
3263 symndx = ELFW(R_SYM) (rel->r_info);
3264 if (symndx) {
3265 /* Note we've already checked for undefined symbols. */
3266
3267 extsym = &symtab[symndx];
3268 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3269 /* Local symbols we look up in the local table to be sure
3270 we get the one that is really intended. */
3271 intsym = f->local_symtab[symndx];
3272 } else {
3273 /* Others we look up in the hash table. */
3274 const char *name;
3275 if (extsym->st_name)
3276 name = strtab + extsym->st_name;
3277 else
3278 name = f->sections[extsym->st_shndx]->name;
3279 intsym = obj_find_symbol(f, name);
3280 }
3281
3282 value = obj_symbol_final_value(f, intsym);
3283 intsym->referenced = 1;
3284 }
3285#if SHT_RELM == SHT_RELA
3286#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3287 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3288 if (!extsym || !extsym->st_name ||
3289 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
3290#endif
3291 value += rel->r_addend;
3292#endif
3293
3294 /* Do it! */
3295 switch (arch_apply_relocation
3296 (f, targsec, symsec, intsym, rel, value)) {
3297 case obj_reloc_ok:
3298 break;
3299
3300 case obj_reloc_overflow:
3301 errmsg = "Relocation overflow";
3302 goto bad_reloc;
3303 case obj_reloc_dangerous:
3304 errmsg = "Dangerous relocation";
3305 goto bad_reloc;
3306 case obj_reloc_unhandled:
3307 errmsg = "Unhandled relocation";
3308 bad_reloc:
3309 if (extsym) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003310 bb_error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003311 (long) ELFW(R_TYPE) (rel->r_info),
3312 strtab + extsym->st_name);
3313 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003314 bb_error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003315 (long) ELFW(R_TYPE) (rel->r_info));
3316 }
3317 ret = 0;
3318 break;
3319 }
3320 }
3321 }
3322
3323 /* Finally, take care of the patches. */
3324
3325 if (f->string_patches) {
3326 struct obj_string_patch *p;
3327 struct obj_section *strsec;
3328 ElfW(Addr) strsec_base;
3329 strsec = obj_find_section(f, ".kstrtab");
3330 strsec_base = strsec->header.sh_addr;
3331
3332 for (p = f->string_patches; p; p = p->next) {
3333 struct obj_section *targsec = f->sections[p->reloc_secidx];
3334 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3335 = strsec_base + p->string_offset;
3336 }
3337 }
3338
3339 if (f->symbol_patches) {
3340 struct obj_symbol_patch *p;
3341
3342 for (p = f->symbol_patches; p; p = p->next) {
3343 struct obj_section *targsec = f->sections[p->reloc_secidx];
3344 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3345 = obj_symbol_final_value(f, p->sym);
3346 }
3347 }
3348
3349 return ret;
3350}
3351
Eric Andersen044228d2001-07-17 01:12:36 +00003352static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003353{
3354 struct obj_section *sec;
3355 ElfW(Addr) base = f->baseaddr;
3356
3357 for (sec = f->load_order; sec; sec = sec->load_next) {
3358 char *secimg;
3359
Eric Andersen2bf658d2001-02-24 20:01:53 +00003360 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003361 continue;
3362
3363 secimg = image + (sec->header.sh_addr - base);
3364
3365 /* Note that we allocated data for NOBITS sections earlier. */
3366 memcpy(secimg, sec->contents, sec->header.sh_size);
3367 }
3368
3369 return 1;
3370}
3371
3372/*======================================================================*/
3373
Eric Andersen044228d2001-07-17 01:12:36 +00003374static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003375{
3376 struct obj_file *f;
3377 ElfW(Shdr) * section_headers;
3378 int shnum, i;
3379 char *shstrtab;
3380
3381 /* Read the file header. */
3382
3383 f = arch_new_file();
3384 memset(f, 0, sizeof(*f));
3385 f->symbol_cmp = strcmp;
3386 f->symbol_hash = obj_elf_hash;
3387 f->load_order_search_start = &f->load_order;
3388
3389 fseek(fp, 0, SEEK_SET);
3390 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003391 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003392 return NULL;
3393 }
3394
3395 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3396 || f->header.e_ident[EI_MAG1] != ELFMAG1
3397 || f->header.e_ident[EI_MAG2] != ELFMAG2
3398 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003399 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003400 return NULL;
3401 }
3402 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3403 || f->header.e_ident[EI_DATA] != ELFDATAM
3404 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3405 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003406 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003407 return NULL;
3408 }
3409 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003410 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003411 return NULL;
3412 }
3413
3414 /* Read the section headers. */
3415
3416 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003417 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003418 (unsigned long) f->header.e_shentsize,
3419 (unsigned long) sizeof(ElfW(Shdr)));
3420 return NULL;
3421 }
3422
3423 shnum = f->header.e_shnum;
3424 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3425 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3426
3427 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3428 fseek(fp, f->header.e_shoff, SEEK_SET);
3429 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003430 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003431 return NULL;
3432 }
3433
3434 /* Read the section data. */
3435
3436 for (i = 0; i < shnum; ++i) {
3437 struct obj_section *sec;
3438
3439 f->sections[i] = sec = arch_new_section();
3440 memset(sec, 0, sizeof(*sec));
3441
3442 sec->header = section_headers[i];
3443 sec->idx = i;
3444
Eric Andersen2bf658d2001-02-24 20:01:53 +00003445 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 case SHT_NULL:
3447 case SHT_NOTE:
3448 case SHT_NOBITS:
3449 /* ignore */
3450 break;
3451
3452 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003453#if LOADBITS
3454 if (!loadprogbits) {
3455 sec->contents = NULL;
3456 break;
3457 }
3458#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003459 case SHT_SYMTAB:
3460 case SHT_STRTAB:
3461 case SHT_RELM:
3462 if (sec->header.sh_size > 0) {
3463 sec->contents = xmalloc(sec->header.sh_size);
3464 fseek(fp, sec->header.sh_offset, SEEK_SET);
3465 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003466 bb_perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003467 return NULL;
3468 }
3469 } else {
3470 sec->contents = NULL;
3471 }
3472 break;
3473
3474#if SHT_RELM == SHT_REL
3475 case SHT_RELA:
Manuel Novoa III cad53642003-03-19 09:13:01 +00003476 bb_error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003477 return NULL;
3478#else
3479 case SHT_REL:
Manuel Novoa III cad53642003-03-19 09:13:01 +00003480 bb_error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003481 return NULL;
3482#endif
3483
3484 default:
3485 if (sec->header.sh_type >= SHT_LOPROC) {
3486 /* Assume processor specific section types are debug
3487 info and can safely be ignored. If this is ever not
3488 the case (Hello MIPS?), don't put ifdefs here but
3489 create an arch_load_proc_section(). */
3490 break;
3491 }
3492
Manuel Novoa III cad53642003-03-19 09:13:01 +00003493 bb_error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003494 (long) sec->header.sh_type);
3495 return NULL;
3496 }
3497 }
3498
3499 /* Do what sort of interpretation as needed by each section. */
3500
3501 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3502
3503 for (i = 0; i < shnum; ++i) {
3504 struct obj_section *sec = f->sections[i];
3505 sec->name = shstrtab + sec->header.sh_name;
3506 }
3507
3508 for (i = 0; i < shnum; ++i) {
3509 struct obj_section *sec = f->sections[i];
3510
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003511 /* .modinfo should be contents only but gcc has no attribute for that.
3512 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3513 */
3514 if (strcmp(sec->name, ".modinfo") == 0)
3515 sec->header.sh_flags &= ~SHF_ALLOC;
3516
Eric Andersen9f16d612000-06-12 23:11:16 +00003517 if (sec->header.sh_flags & SHF_ALLOC)
3518 obj_insert_section_load_order(f, sec);
3519
3520 switch (sec->header.sh_type) {
3521 case SHT_SYMTAB:
3522 {
3523 unsigned long nsym, j;
3524 char *strtab;
3525 ElfW(Sym) * sym;
3526
3527 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003528 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003529 (unsigned long) sec->header.sh_entsize,
3530 (unsigned long) sizeof(ElfW(Sym)));
3531 return NULL;
3532 }
3533
3534 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3535 strtab = f->sections[sec->header.sh_link]->contents;
3536 sym = (ElfW(Sym) *) sec->contents;
3537
3538 /* Allocate space for a table of local symbols. */
3539 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003540 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003541
3542 /* Insert all symbols into the hash table. */
3543 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
Eric Andersenbf833552003-08-13 19:56:33 +00003544 ElfW(Addr) val = sym->st_value;
Eric Andersen9f16d612000-06-12 23:11:16 +00003545 const char *name;
3546 if (sym->st_name)
3547 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003548 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003549 name = f->sections[sym->st_shndx]->name;
3550
Eric Andersenbf833552003-08-13 19:56:33 +00003551#if defined(__SH5__)
3552 /*
3553 * For sh64 it is possible that the target of a branch
3554 * requires a mode switch (32 to 16 and back again).
3555 *
3556 * This is implied by the lsb being set in the target
3557 * address for SHmedia mode and clear for SHcompact.
3558 */
3559 val |= sym->st_other & 4;
3560#endif
3561
Eric Andersen9f16d612000-06-12 23:11:16 +00003562 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
Eric Andersenbf833552003-08-13 19:56:33 +00003563 val, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003564 }
3565 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003566 break;
3567
3568 case SHT_RELM:
3569 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003570 bb_error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003571 (unsigned long) sec->header.sh_entsize,
3572 (unsigned long) sizeof(ElfW(RelM)));
3573 return NULL;
3574 }
3575 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003576 /* XXX Relocation code from modutils-2.3.19 is not here.
3577 * Why? That's about 20 lines of code from obj/obj_load.c,
3578 * which gets done in a second pass through the sections.
3579 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003580 }
3581 }
3582
3583 return f;
3584}
3585
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003586#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003587/*
3588 * load the unloaded sections directly into the memory allocated by
3589 * kernel for the module
3590 */
3591
Eric Andersenac5dbd12001-08-22 05:26:08 +00003592static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003593{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003594 ElfW(Addr) base = f->baseaddr;
3595 struct obj_section* sec;
3596
3597 for (sec = f->load_order; sec; sec = sec->load_next) {
3598
3599 /* section already loaded? */
3600 if (sec->contents != NULL)
3601 continue;
3602
3603 if (sec->header.sh_size == 0)
3604 continue;
3605
3606 sec->contents = imagebase + (sec->header.sh_addr - base);
3607 fseek(fp, sec->header.sh_offset, SEEK_SET);
3608 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003609 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003610 return 0;
3611 }
3612
3613 }
3614 return 1;
3615}
3616#endif
3617
Eric Andersen9f16d612000-06-12 23:11:16 +00003618static void hide_special_symbols(struct obj_file *f)
3619{
3620 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003621 SPFX "cleanup_module",
3622 SPFX "init_module",
3623 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003624 NULL
3625 };
3626
3627 struct obj_symbol *sym;
3628 const char *const *p;
3629
3630 for (p = specials; *p; ++p)
3631 if ((sym = obj_find_symbol(f, *p)) != NULL)
3632 sym->info =
3633 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3634}
3635
Glenn L McGrath759515c2003-08-30 06:00:33 +00003636
Eric Andersen71ae64b2002-10-10 04:20:21 +00003637#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003638static int obj_gpl_license(struct obj_file *f, const char **license)
3639{
3640 struct obj_section *sec;
3641 /* This list must match *exactly* the list of allowable licenses in
3642 * linux/include/linux/module.h. Checking for leading "GPL" will not
3643 * work, somebody will use "GPL sucks, this is proprietary".
3644 */
3645 static const char *gpl_licenses[] = {
3646 "GPL",
3647 "GPL v2",
3648 "GPL and additional rights",
3649 "Dual BSD/GPL",
3650 "Dual MPL/GPL",
3651 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003652
Eric Andersen166fa462002-09-16 05:30:24 +00003653 if ((sec = obj_find_section(f, ".modinfo"))) {
3654 const char *value, *ptr, *endptr;
3655 ptr = sec->contents;
3656 endptr = ptr + sec->header.sh_size;
3657 while (ptr < endptr) {
3658 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3659 int i;
3660 if (license)
3661 *license = value+1;
3662 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3663 if (strcmp(value+1, gpl_licenses[i]) == 0)
3664 return(0);
3665 }
3666 return(2);
3667 }
3668 if (strchr(ptr, '\0'))
3669 ptr = strchr(ptr, '\0') + 1;
3670 else
3671 ptr = endptr;
3672 }
3673 }
3674 return(1);
3675}
3676
3677#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3678#define TAINT_PROPRIETORY_MODULE (1<<0)
3679#define TAINT_FORCED_MODULE (1<<1)
3680#define TAINT_UNSAFE_SMP (1<<2)
3681#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3682
3683static void set_tainted(struct obj_file *f, int fd, char *m_name,
3684 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3685{
3686 char buf[80];
3687 int oldval;
3688 static int first = 1;
3689 if (fd < 0 && !kernel_has_tainted)
3690 return; /* New modutils on old kernel */
3691 printf("Warning: loading %s will taint the kernel: %s%s\n",
3692 m_name, text1, text2);
3693 if (first) {
3694 printf(" See %s for information about tainted modules\n", TAINT_URL);
3695 first = 0;
3696 }
3697 if (fd >= 0) {
3698 read(fd, buf, sizeof(buf)-1);
3699 buf[sizeof(buf)-1] = '\0';
3700 oldval = strtoul(buf, NULL, 10);
3701 sprintf(buf, "%d\n", oldval | taint);
3702 write(fd, buf, strlen(buf));
3703 }
3704}
3705
3706/* Check if loading this module will taint the kernel. */
3707static void check_tainted_module(struct obj_file *f, char *m_name)
3708{
3709 static const char tainted_file[] = TAINT_FILENAME;
3710 int fd, kernel_has_tainted;
3711 const char *ptr;
3712
3713 kernel_has_tainted = 1;
3714 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3715 if (errno == ENOENT)
3716 kernel_has_tainted = 0;
3717 else if (errno == EACCES)
3718 kernel_has_tainted = 1;
3719 else {
3720 perror(tainted_file);
3721 kernel_has_tainted = 0;
3722 }
3723 }
3724
3725 switch (obj_gpl_license(f, &ptr)) {
3726 case 0:
3727 break;
3728 case 1:
3729 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3730 break;
3731 case 2:
3732 /* The module has a non-GPL license so we pretend that the
3733 * kernel always has a taint flag to get a warning even on
3734 * kernels without the proc flag.
3735 */
3736 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3737 break;
3738 default:
3739 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3740 break;
3741 }
3742
3743 if (flag_force_load)
3744 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3745
3746 if (fd >= 0)
3747 close(fd);
3748}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003749#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3750#define check_tainted_module(x, y) do { } while(0);
3751#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003752
Eric Andersen889dd202003-01-23 04:48:34 +00003753#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3754/* add module source, timestamp, kernel version and a symbol for the
3755 * start of some sections. this info is used by ksymoops to do better
3756 * debugging.
3757 */
3758static int
3759get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3760{
3761#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
3762 if (get_modinfo_value(f, "kernel_version") == NULL)
3763 return old_get_module_version(f, str);
3764 else
3765 return new_get_module_version(f, str);
3766#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3767 strncpy(str, "???", sizeof(str));
3768 return -1;
3769#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3770}
3771
3772/* add module source, timestamp, kernel version and a symbol for the
3773 * start of some sections. this info is used by ksymoops to do better
3774 * debugging.
3775 */
3776static void
3777add_ksymoops_symbols(struct obj_file *f, const char *filename,
3778 const char *m_name)
3779{
3780 static const char symprefix[] = "__insmod_";
3781 struct obj_section *sec;
3782 struct obj_symbol *sym;
3783 char *name, *absolute_filename;
3784 char str[STRVERSIONLEN], real[PATH_MAX];
3785 int i, l, lm_name, lfilename, use_ksymtab, version;
3786 struct stat statbuf;
3787
3788 static const char *section_names[] = {
3789 ".text",
3790 ".rodata",
3791 ".data",
3792 ".bss"
3793 ".sbss"
3794 };
3795
3796 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003797 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003798 }
3799 else {
3800 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003801 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003802 errno = save_errno;
3803 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003804 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003805 }
3806
3807 lm_name = strlen(m_name);
3808 lfilename = strlen(absolute_filename);
3809
3810 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3811 * are not to be exported. otherwise leave ksymtab alone for now, the
3812 * "export all symbols" compatibility code will export these symbols later.
3813 */
3814 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3815
3816 if ((sec = obj_find_section(f, ".this"))) {
3817 /* tag the module header with the object name, last modified
3818 * timestamp and module version. worst case for module version
3819 * is 0xffffff, decimal 16777215. putting all three fields in
3820 * one symbol is less readable but saves kernel space.
3821 */
3822 l = sizeof(symprefix)+ /* "__insmod_" */
3823 lm_name+ /* module name */
3824 2+ /* "_O" */
3825 lfilename+ /* object filename */
3826 2+ /* "_M" */
3827 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3828 2+ /* "_V" */
3829 8+ /* version in dec */
3830 1; /* nul */
3831 name = xmalloc(l);
3832 if (stat(absolute_filename, &statbuf) != 0)
3833 statbuf.st_mtime = 0;
3834 version = get_module_version(f, str); /* -1 if not found */
3835 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
3836 symprefix, m_name, absolute_filename,
3837 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3838 version);
3839 sym = obj_add_symbol(f, name, -1,
3840 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3841 sec->idx, sec->header.sh_addr, 0);
3842 if (use_ksymtab)
3843 new_add_ksymtab(f, sym);
3844 }
3845 free(absolute_filename);
3846#ifdef _NOT_SUPPORTED_
3847 /* record where the persistent data is going, same address as previous symbol */
3848
3849 if (f->persist) {
3850 l = sizeof(symprefix)+ /* "__insmod_" */
3851 lm_name+ /* module name */
3852 2+ /* "_P" */
3853 strlen(f->persist)+ /* data store */
3854 1; /* nul */
3855 name = xmalloc(l);
3856 snprintf(name, l, "%s%s_P%s",
3857 symprefix, m_name, f->persist);
3858 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3859 sec->idx, sec->header.sh_addr, 0);
3860 if (use_ksymtab)
3861 new_add_ksymtab(f, sym);
3862 }
3863#endif /* _NOT_SUPPORTED_ */
3864 /* tag the desired sections if size is non-zero */
3865
3866 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3867 if ((sec = obj_find_section(f, section_names[i])) &&
3868 sec->header.sh_size) {
3869 l = sizeof(symprefix)+ /* "__insmod_" */
3870 lm_name+ /* module name */
3871 2+ /* "_S" */
3872 strlen(sec->name)+ /* section name */
3873 2+ /* "_L" */
3874 8+ /* length in dec */
3875 1; /* nul */
3876 name = xmalloc(l);
3877 snprintf(name, l, "%s%s_S%s_L%ld",
3878 symprefix, m_name, sec->name,
3879 (long)sec->header.sh_size);
3880 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3881 sec->idx, sec->header.sh_addr, 0);
3882 if (use_ksymtab)
3883 new_add_ksymtab(f, sym);
3884 }
3885 }
3886}
3887#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3888
Eric Andersenbe65c352003-01-23 04:57:35 +00003889#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3890static void print_load_map(struct obj_file *f)
3891{
3892 struct obj_symbol *sym;
3893 struct obj_symbol **all, **p;
3894 struct obj_section *sec;
3895 int i, nsyms, *loaded;
3896
3897 /* Report on the section layout. */
3898
3899 printf("Sections: Size %-*s Align\n",
3900 (int) (2 * sizeof(void *)), "Address");
3901
3902 for (sec = f->load_order; sec; sec = sec->load_next) {
3903 int a;
3904 unsigned long tmp;
3905
3906 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3907 tmp >>= 1;
3908 if (a == -1)
3909 a = 0;
3910
3911 printf("%-15s %08lx %0*lx 2**%d\n",
3912 sec->name,
3913 (long)sec->header.sh_size,
3914 (int) (2 * sizeof(void *)),
3915 (long)sec->header.sh_addr,
3916 a);
3917 }
3918#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3919 /* Quick reference which section indicies are loaded. */
3920
3921 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3922 while (--i >= 0)
3923 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3924
3925 /* Collect the symbols we'll be listing. */
3926
3927 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3928 for (sym = f->symtab[i]; sym; sym = sym->next)
3929 if (sym->secidx <= SHN_HIRESERVE
3930 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3931 ++nsyms;
3932
3933 all = alloca(nsyms * sizeof(struct obj_symbol *));
3934
3935 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3936 for (sym = f->symtab[i]; sym; sym = sym->next)
3937 if (sym->secidx <= SHN_HIRESERVE
3938 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3939 *p++ = sym;
3940
3941 /* And list them. */
3942 printf("\nSymbols:\n");
3943 for (p = all; p < all + nsyms; ++p) {
3944 char type = '?';
3945 unsigned long value;
3946
3947 sym = *p;
3948 if (sym->secidx == SHN_ABS) {
3949 type = 'A';
3950 value = sym->value;
3951 } else if (sym->secidx == SHN_UNDEF) {
3952 type = 'U';
3953 value = 0;
3954 } else {
3955 sec = f->sections[sym->secidx];
3956
3957 if (sec->header.sh_type == SHT_NOBITS)
3958 type = 'B';
3959 else if (sec->header.sh_flags & SHF_ALLOC) {
3960 if (sec->header.sh_flags & SHF_EXECINSTR)
3961 type = 'T';
3962 else if (sec->header.sh_flags & SHF_WRITE)
3963 type = 'D';
3964 else
3965 type = 'R';
3966 }
3967 value = sym->value + sec->header.sh_addr;
3968 }
3969
3970 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
3971 type = tolower(type);
3972
3973 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3974 type, sym->name);
3975 }
3976#endif
3977}
3978
3979#endif
3980
Eric Andersen9f16d612000-06-12 23:11:16 +00003981extern int insmod_main( int argc, char **argv)
3982{
Eric Andersena18aaf12001-01-24 19:07:09 +00003983 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003984 int k_crcs;
3985 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003986 int len;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003987 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003988 unsigned long m_size;
3989 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003990 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003991 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003992 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003993 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003994 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003995#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003996 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003997 char m_strversion[STRVERSIONLEN];
3998 int m_version;
3999 int m_crcs;
4000#endif
Eric Andersen61f83052002-06-22 17:15:42 +00004001#ifdef CONFIG_FEATURE_CLEAN_UP
4002 FILE *fp = 0;
4003#else
4004 FILE *fp;
4005#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00004006#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4007 int flag_print_load_map = 0;
4008#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00004009
Erik Andersene49d5ec2000-02-08 19:58:47 +00004010 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00004011#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4012 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0) {
4013#else
Eric Andersenb493dec2002-07-02 19:14:23 +00004014 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
Eric Andersenbe65c352003-01-23 04:57:35 +00004015#endif
Eric Andersena18aaf12001-01-24 19:07:09 +00004016 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004017 case 'f': /* force loading */
4018 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004019 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00004020 case 'k': /* module loaded by kerneld, auto-cleanable */
4021 flag_autoclean = 1;
4022 break;
Eric Andersenc088c582002-05-03 10:34:35 +00004023 case 's': /* log to syslog */
4024 /* log to syslog -- not supported */
4025 /* but kernel needs this for request_module(), */
4026 /* as this calls: modprobe -k -s -- <module> */
4027 /* so silently ignore this flag */
4028 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00004029 case 'v': /* verbose output */
4030 flag_verbose = 1;
4031 break;
Eric Andersenb493dec2002-07-02 19:14:23 +00004032 case 'q': /* silent */
4033 flag_quiet = 1;
4034 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00004035 case 'x': /* do not export externs */
4036 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004037 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00004038 case 'o': /* name the output module */
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00004039 free(m_name);
Manuel Novoa III cad53642003-03-19 09:13:01 +00004040 m_name = bb_xstrdup(optarg);
Eric Andersen155c89b2001-01-25 04:11:06 +00004041 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00004042 case 'L': /* Stub warning */
4043 /* This is needed for compatibility with modprobe.
4044 * In theory, this does locking, but we don't do
4045 * that. So be careful and plan your life around not
4046 * loading the same module 50 times concurrently. */
4047 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004048#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4049 case 'm': /* print module load map */
4050 flag_print_load_map = 1;
4051 break;
4052#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +00004053 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004054 bb_show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00004055 }
Erik Andersend387d011999-12-21 02:55:11 +00004056 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004057
4058 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004059 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00004060 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004061
Erik Andersene49d5ec2000-02-08 19:58:47 +00004062 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00004063 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00004064 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004065 len = strlen(tmp);
4066
Eric Andersen6fb4e482002-06-06 14:24:57 +00004067 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4068 len-=2;
4069 tmp[len] = '\0';
Eric Andersen155c89b2001-01-25 04:11:06 +00004070 }
Eric Andersen2d342152002-06-18 05:16:25 +00004071
Manuel Novoa III cad53642003-03-19 09:13:01 +00004072 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004073
Eric Andersen61f83052002-06-22 17:15:42 +00004074 if (!m_name) {
4075 m_name = tmp;
4076 } else {
4077 free(tmp1);
4078 tmp1 = 0; /* flag for free(m_name) before exit() */
4079 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004080
Eric Andersen14d35432001-05-14 17:07:32 +00004081 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004082 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4083 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004084 struct utsname myuname;
4085
4086 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4087 * but do not error out yet if we fail to find it... */
4088 if (uname(&myuname) == 0) {
Robert Griebld378c312002-07-19 00:05:54 +00004089 char *module_dir;
4090 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004091 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004092
4093 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004094 /* Jump through hoops in case /lib/modules/`uname -r`
4095 * is a symlink. We do not want recursive_action to
4096 * follow symlinks, but we do want to follow the
4097 * /lib/modules/`uname -r` dir, So resolve it ourselves
4098 * if it is a link... */
Robert Griebld378c312002-07-19 00:05:54 +00004099 if (realpath (tmdn, real_module_dir) == NULL)
4100 module_dir = tmdn;
4101 else
4102 module_dir = real_module_dir;
4103 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00004104 check_module_name_match, 0, m_fullName);
Robert Griebld378c312002-07-19 00:05:54 +00004105 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004106 }
4107
4108 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004109 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004110 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004111 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004112
4113 free(m_filename);
4114 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004115 if (realpath (_PATH_MODULES, module_dir) == NULL)
4116 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004117 /* No module found under /lib/modules/`uname -r`, this
4118 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004119 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
4120 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004121 {
Eric Andersen61f83052002-06-22 17:15:42 +00004122 if (m_filename == 0
Eric Andersen14d35432001-05-14 17:07:32 +00004123 || ((fp = fopen(m_filename, "r")) == NULL))
4124 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004125 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004126 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004127 }
4128 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004129 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004130 }
4131 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004132 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004133
Eric Andersen14d35432001-05-14 17:07:32 +00004134 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004135
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004136#ifdef CONFIG_FEATURE_REALLY_NEW_MODULE_INTERFACE
4137 if (create_module(NULL, 0) < 0 && errno == ENOSYS) {
4138 optind--;
4139 argv[optind] = m_filename;
4140 return insmod_ng_main(argc - optind, argv + optind);
4141 }
4142#endif
4143
Eric Andersen8ae319a2001-05-21 16:09:18 +00004144 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004145 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004146
Eric Andersen9f16d612000-06-12 23:11:16 +00004147 if (get_modinfo_value(f, "kernel_version") == NULL)
4148 m_has_modinfo = 0;
4149 else
4150 m_has_modinfo = 1;
4151
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004152#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004153 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004154 if (!flag_quiet) {
4155 if (uname(&uts_info) < 0)
4156 uts_info.release[0] = '\0';
4157 if (m_has_modinfo) {
4158 m_version = new_get_module_version(f, m_strversion);
Eric Andersen9f16d612000-06-12 23:11:16 +00004159 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00004160 m_version = old_get_module_version(f, m_strversion);
4161 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004162 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004163 "compiled for");
4164 goto out;
4165 }
4166 }
4167
4168 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4169 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004170 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004171 "\t%s was compiled for kernel version %s\n"
4172 "\twhile this kernel is version %s",
4173 m_filename, m_strversion, uts_info.release);
4174 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004175 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004176 "\t%s was compiled for kernel version %s\n"
4177 "\twhile this kernel is version %s.",
4178 m_filename, m_strversion, uts_info.release);
4179 goto out;
4180 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004181 }
4182 }
4183 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004184#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004185
4186 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
4187
4188 if (k_new_syscalls) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004189#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00004190 if (!new_get_kernel_symbols())
4191 goto out;
4192 k_crcs = new_is_kernel_checksummed();
4193#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004194 bb_error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004195 goto out;
4196#endif
4197 } else {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004198#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00004199 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004200 goto out;
4201 k_crcs = old_is_kernel_checksummed();
4202#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004203 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004204 goto out;
4205#endif
4206 }
4207
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004208#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004209 if (m_has_modinfo)
4210 m_crcs = new_is_module_checksummed(f);
4211 else
4212 m_crcs = old_is_module_checksummed(f);
4213
4214 if (m_crcs != k_crcs)
4215 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004216#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004217
Erik Andersene49d5ec2000-02-08 19:58:47 +00004218 /* Let the module know about the kernel symbols. */
4219 add_kernel_symbols(f);
4220
Eric Andersen9f16d612000-06-12 23:11:16 +00004221 /* Allocate common symbols, symbol tables, and string tables. */
4222
4223 if (k_new_syscalls
4224 ? !new_create_this_module(f, m_name)
4225 : !old_create_mod_use_count(f))
4226 {
4227 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004228 }
4229
Eric Andersen9f16d612000-06-12 23:11:16 +00004230 if (!obj_check_undefineds(f)) {
4231 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004232 }
4233 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004234 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004235
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004236 /* done with the module name, on to the optional var=value arguments */
4237 ++optind;
4238
Eric Andersen9f16d612000-06-12 23:11:16 +00004239 if (optind < argc) {
4240 if (m_has_modinfo
4241 ? !new_process_module_arguments(f, argc - optind, argv + optind)
4242 : !old_process_module_arguments(f, argc - optind, argv + optind))
4243 {
4244 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004245 }
4246 }
4247
Eric Andersen9f16d612000-06-12 23:11:16 +00004248 arch_create_got(f);
4249 hide_special_symbols(f);
4250
Eric Andersen889dd202003-01-23 04:48:34 +00004251#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4252 add_ksymoops_symbols(f, m_filename, m_name);
4253#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4254
Eric Andersen9f16d612000-06-12 23:11:16 +00004255 if (k_new_syscalls)
4256 new_create_module_ksymtab(f);
4257
Erik Andersene49d5ec2000-02-08 19:58:47 +00004258 /* Find current size of the module */
4259 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004260
4261
Erik Andersene49d5ec2000-02-08 19:58:47 +00004262 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004263 if (m_addr == -1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004264 case EEXIST:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004265 bb_error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00004266 goto out;
4267 case ENOMEM:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004268 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00004269 m_size);
4270 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00004271 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004272 bb_perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00004273 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004274 }
Erik Andersend387d011999-12-21 02:55:11 +00004275
Eric Andersen8ae319a2001-05-21 16:09:18 +00004276#if !LOADBITS
4277 /*
4278 * the PROGBITS section was not loaded by the obj_load
4279 * now we can load them directly into the kernel memory
4280 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004281 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004282 delete_module(m_name);
4283 goto out;
4284 }
4285#endif
4286
Eric Andersen9f16d612000-06-12 23:11:16 +00004287 if (!obj_relocate(f, m_addr)) {
4288 delete_module(m_name);
4289 goto out;
4290 }
Erik Andersend387d011999-12-21 02:55:11 +00004291
Eric Andersen9f16d612000-06-12 23:11:16 +00004292 if (k_new_syscalls
4293 ? !new_init_module(m_name, f, m_size)
4294 : !old_init_module(m_name, f, m_size))
4295 {
4296 delete_module(m_name);
4297 goto out;
4298 }
4299
Eric Andersenbe65c352003-01-23 04:57:35 +00004300#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4301 if(flag_print_load_map)
4302 print_load_map(f);
4303#endif
4304
Matt Kraai3e856ce2000-12-01 02:55:13 +00004305 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004306
4307out:
Eric Andersen61f83052002-06-22 17:15:42 +00004308#ifdef CONFIG_FEATURE_CLEAN_UP
4309 if(fp)
Erik Andersene49d5ec2000-02-08 19:58:47 +00004310 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004311 if(tmp1) {
4312 free(tmp1);
4313 } else {
4314 free(m_name);
4315 }
4316 free(m_filename);
4317#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004318 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004319}