blob: 84617fa4856dd411b07808e4c21b23d875c4c262 [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 *
5 * This version of insmod supports x86, ARM, SH3/4, 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 Andersencffd5022002-05-24 06:50:15 +000022 * Magnus Damm <damm@opensource.se> 22-May-2002.
23 * The plt and got code are now using the same structs.
24 * Added generic linked list code to fully support PowerPC.
25 * Replaced the mess in arch_apply_relocation() with architecture blocks.
26 * The arch_create_got() function got cleaned up with architecture blocks.
27 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
28 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000029 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
30 * PowerPC specific code stolen from modutils-2.3.16,
31 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
32 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000033 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000034 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000035 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
36 * based on modutils-2.4.2
37 * MIPS specific support for Elf loading and relocation.
38 * Copyright 1996, 1997 Linux International.
39 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
40 *
Eric Andersen9f16d612000-06-12 23:11:16 +000041 * Based almost entirely on the Linux modutils-2.3.11 implementation.
42 * Copyright 1996, 1997 Linux International.
43 * New implementation contributed by Richard Henderson <rth@tamu.edu>
44 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
45 * Restructured (and partly rewritten) by:
46 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000047 *
48 * This program is free software; you can redistribute it and/or modify
49 * it under the terms of the GNU General Public License as published by
50 * the Free Software Foundation; either version 2 of the License, or
51 * (at your option) any later version.
52 *
53 * This program is distributed in the hope that it will be useful,
54 * but WITHOUT ANY WARRANTY; without even the implied warranty of
55 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56 * General Public License for more details.
57 *
58 * You should have received a copy of the GNU General Public License
59 * along with this program; if not, write to the Free Software
60 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61 *
62 */
63
Erik Andersen02104321999-12-17 18:57:34 +000064#include <stdlib.h>
65#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000066#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000067#include <errno.h>
68#include <unistd.h>
69#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000070#include <ctype.h>
71#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000072#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000073#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000074#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000075#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000076#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000077
Eric Andersenbdfd0d72001-10-24 05:00:29 +000078#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
79# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen64c8b172001-04-05 07:33:10 +000080# define new_sys_init_module init_module
81#else
82# define old_sys_init_module init_module
83#endif
84
Eric Andersenbdfd0d72001-10-24 05:00:29 +000085#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +000086#define LOADBITS 0
87#else
88#define LOADBITS 1
89#endif
90
Eric Andersen90fe7fe2001-02-20 20:47:08 +000091
92#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000093#define CONFIG_USE_PLT_ENTRIES
94#define CONFIG_PLT_ENTRY_SIZE 8
95#define CONFIG_USE_GOT_ENTRIES
96#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +000097#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000103#endif
104
Eric Andersenbf77f612003-01-23 06:02:39 +0000105#if defined(__s390__)
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000106#define CONFIG_USE_PLT_ENTRIES
107#define CONFIG_PLT_ENTRY_SIZE 8
108#define CONFIG_USE_GOT_ENTRIES
109#define CONFIG_GOT_ENTRY_SIZE 8
110#define CONFIG_USE_SINGLE
Eric Andersenbf77f612003-01-23 06:02:39 +0000111
112#define MATCH_MACHINE(x) (x == EM_S390)
113#define SHT_RELM SHT_RELA
114#define Elf32_RelM Elf32_Rela
115#define ELFCLASSM ELFCLASS32
116#endif
117
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000118#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000119#define CONFIG_USE_GOT_ENTRIES
120#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000121#define CONFIG_USE_SINGLE
122
123#ifndef EM_486
124#define MATCH_MACHINE(x) (x == EM_386)
125#else
126#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
127#endif
128
129#define SHT_RELM SHT_REL
130#define Elf32_RelM Elf32_Rel
131#define ELFCLASSM ELFCLASS32
132#endif
133
134#if defined(__mc68000__)
135#define CONFIG_USE_GOT_ENTRIES
136#define CONFIG_GOT_ENTRY_SIZE 4
137#define CONFIG_USE_SINGLE
138
139#define MATCH_MACHINE(x) (x == EM_68K)
140#define SHT_RELM SHT_RELA
141#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000142#endif
143
Eric Andersen2bf658d2001-02-24 20:01:53 +0000144#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000145/* Account for ELF spec changes. */
146#ifndef EM_MIPS_RS3_LE
147#ifdef EM_MIPS_RS4_BE
148#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
149#else
150#define EM_MIPS_RS3_LE 10
151#endif
152#endif /* !EM_MIPS_RS3_LE */
153
154#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
155#define SHT_RELM SHT_REL
156#define Elf32_RelM Elf32_Rel
157#define ELFCLASSM ELFCLASS32
158#define ARCHDATAM "__dbe_table"
159#endif
160
161#if defined(__powerpc__)
162#define CONFIG_USE_PLT_ENTRIES
163#define CONFIG_PLT_ENTRY_SIZE 16
164#define CONFIG_USE_PLT_LIST
165#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
166#define CONFIG_USE_LIST
167
168#define MATCH_MACHINE(x) (x == EM_PPC)
169#define SHT_RELM SHT_RELA
170#define Elf32_RelM Elf32_Rela
171#define ELFCLASSM ELFCLASS32
172#define ARCHDATAM "__ftr_fixup"
173#endif
174
175#if defined(__sh__)
176#define CONFIG_USE_GOT_ENTRIES
177#define CONFIG_GOT_ENTRY_SIZE 4
178#define CONFIG_USE_SINGLE
179
180#define MATCH_MACHINE(x) (x == EM_SH)
181#define SHT_RELM SHT_RELA
182#define Elf32_RelM Elf32_Rela
183#define ELFCLASSM ELFCLASS32
184
185/* the SH changes have only been tested on the SH4 in =little endian= mode */
186/* I'm not sure about big endian, so let's warn: */
187
188#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
189#error insmod.c may require changes for use on big endian SH4/SH3
190#endif
191
192/* it may or may not work on the SH1/SH2... So let's error on those
193 also */
194#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
195#error insmod.c may require changes for non-SH3/SH4 use
196#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000197#endif
198
Miles Baderae28b042002-04-01 09:34:25 +0000199#if defined (__v850e__)
200#define CONFIG_USE_PLT_ENTRIES
201#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000202#define CONFIG_USE_SINGLE
203
204#ifndef EM_CYGNUS_V850 /* grumble */
205#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000206#endif
207
Eric Andersencffd5022002-05-24 06:50:15 +0000208#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
209#define SHT_RELM SHT_RELA
210#define Elf32_RelM Elf32_Rela
211#define ELFCLASSM ELFCLASS32
212
213#define SYMBOL_PREFIX "_"
214#endif
215
216#ifndef SHT_RELM
217#error Sorry, but insmod.c does not yet support this architecture...
218#endif
219
220
Eric Andersen9f16d612000-06-12 23:11:16 +0000221//----------------------------------------------------------------------------
222//--------modutils module.h, lines 45-242
223//----------------------------------------------------------------------------
224
225/* Definitions for the Linux module syscall interface.
226 Copyright 1996, 1997 Linux International.
227
228 Contributed by Richard Henderson <rth@tamu.edu>
229
230 This file is part of the Linux modutils.
231
232 This program is free software; you can redistribute it and/or modify it
233 under the terms of the GNU General Public License as published by the
234 Free Software Foundation; either version 2 of the License, or (at your
235 option) any later version.
236
237 This program is distributed in the hope that it will be useful, but
238 WITHOUT ANY WARRANTY; without even the implied warranty of
239 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
240 General Public License for more details.
241
242 You should have received a copy of the GNU General Public License
243 along with this program; if not, write to the Free Software Foundation,
244 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
245
246
247#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000248static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000249
Eric Andersen85e5e722003-07-22 08:56:55 +0000250#ident "$Id: insmod.c,v 1.99 2003/07/22 08:56:50 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000251
252/* This file contains the structures used by the 2.0 and 2.1 kernels.
253 We do not use the kernel headers directly because we do not wish
254 to be dependant on a particular kernel version to compile insmod. */
255
256
257/*======================================================================*/
258/* The structures used by Linux 2.0. */
259
260/* The symbol format used by get_kernel_syms(2). */
261struct old_kernel_sym
262{
263 unsigned long value;
264 char name[60];
265};
266
267struct old_module_ref
268{
269 unsigned long module; /* kernel addresses */
270 unsigned long next;
271};
272
273struct old_module_symbol
274{
275 unsigned long addr;
276 unsigned long name;
277};
278
279struct old_symbol_table
280{
281 int size; /* total, including string table!!! */
282 int n_symbols;
283 int n_refs;
284 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
285 struct old_module_ref ref[0]; /* actual size defined by n_refs */
286};
287
288struct old_mod_routines
289{
290 unsigned long init;
291 unsigned long cleanup;
292};
293
294struct old_module
295{
296 unsigned long next;
297 unsigned long ref; /* the list of modules that refer to me */
298 unsigned long symtab;
299 unsigned long name;
300 int size; /* size of module in pages */
301 unsigned long addr; /* address of module */
302 int state;
303 unsigned long cleanup; /* cleanup routine */
304};
305
306/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000307static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000308
309int get_kernel_syms(struct old_kernel_sym *);
310int old_sys_init_module(const char *name, char *code, unsigned codesize,
311 struct old_mod_routines *, struct old_symbol_table *);
312
313/*======================================================================*/
314/* For sizeof() which are related to the module platform and not to the
315 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
316
317#define tgt_sizeof_char sizeof(char)
318#define tgt_sizeof_short sizeof(short)
319#define tgt_sizeof_int sizeof(int)
320#define tgt_sizeof_long sizeof(long)
321#define tgt_sizeof_char_p sizeof(char *)
322#define tgt_sizeof_void_p sizeof(void *)
323#define tgt_long long
324
325#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
326#undef tgt_sizeof_long
327#undef tgt_sizeof_char_p
328#undef tgt_sizeof_void_p
329#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000330static const int tgt_sizeof_long = 8;
331static const int tgt_sizeof_char_p = 8;
332static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000333#define tgt_long long long
334#endif
335
336/*======================================================================*/
337/* The structures used in Linux 2.1. */
338
339/* Note: new_module_symbol does not use tgt_long intentionally */
340struct new_module_symbol
341{
342 unsigned long value;
343 unsigned long name;
344};
345
346struct new_module_persist;
347
348struct new_module_ref
349{
350 unsigned tgt_long dep; /* kernel addresses */
351 unsigned tgt_long ref;
352 unsigned tgt_long next_ref;
353};
354
355struct new_module
356{
357 unsigned tgt_long size_of_struct; /* == sizeof(module) */
358 unsigned tgt_long next;
359 unsigned tgt_long name;
360 unsigned tgt_long size;
361
362 tgt_long usecount;
363 unsigned tgt_long flags; /* AUTOCLEAN et al */
364
365 unsigned nsyms;
366 unsigned ndeps;
367
368 unsigned tgt_long syms;
369 unsigned tgt_long deps;
370 unsigned tgt_long refs;
371 unsigned tgt_long init;
372 unsigned tgt_long cleanup;
373 unsigned tgt_long ex_table_start;
374 unsigned tgt_long ex_table_end;
375#ifdef __alpha__
376 unsigned tgt_long gp;
377#endif
378 /* Everything after here is extension. */
379 unsigned tgt_long persist_start;
380 unsigned tgt_long persist_end;
381 unsigned tgt_long can_unload;
382 unsigned tgt_long runsize;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000383#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen8ae319a2001-05-21 16:09:18 +0000384 const char *kallsyms_start; /* All symbols for kernel debugging */
385 const char *kallsyms_end;
386 const char *archdata_start; /* arch specific data for module */
387 const char *archdata_end;
388 const char *kernel_data; /* Reserved for kernel internal use */
389#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000390};
391
Eric Andersencffd5022002-05-24 06:50:15 +0000392#ifdef ARCHDATAM
393#define ARCHDATA_SEC_NAME ARCHDATAM
394#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000395#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000396#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000397#define KALLSYMS_SEC_NAME "__kallsyms"
398
399
Eric Andersen9f16d612000-06-12 23:11:16 +0000400struct new_module_info
401{
402 unsigned long addr;
403 unsigned long size;
404 unsigned long flags;
405 long usecount;
406};
407
408/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000409static const int NEW_MOD_RUNNING = 1;
410static const int NEW_MOD_DELETED = 2;
411static const int NEW_MOD_AUTOCLEAN = 4;
412static const int NEW_MOD_VISITED = 8;
413static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000414
Eric Andersen64c8b172001-04-05 07:33:10 +0000415int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000416int query_module(const char *name, int which, void *buf, size_t bufsize,
417 size_t *ret);
418
419/* Values for query_module's which. */
420
Mark Whitley59ab0252001-01-23 22:30:04 +0000421static const int QM_MODULES = 1;
422static const int QM_DEPS = 2;
423static const int QM_REFS = 3;
424static const int QM_SYMBOLS = 4;
425static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000426
427/*======================================================================*/
428/* The system calls unchanged between 2.0 and 2.1. */
429
430unsigned long create_module(const char *, size_t);
431int delete_module(const char *);
432
433
434#endif /* module.h */
435
436//----------------------------------------------------------------------------
437//--------end of modutils module.h
438//----------------------------------------------------------------------------
439
440
441
442//----------------------------------------------------------------------------
443//--------modutils obj.h, lines 253-462
444//----------------------------------------------------------------------------
445
446/* Elf object file loading and relocation routines.
447 Copyright 1996, 1997 Linux International.
448
449 Contributed by Richard Henderson <rth@tamu.edu>
450
451 This file is part of the Linux modutils.
452
453 This program is free software; you can redistribute it and/or modify it
454 under the terms of the GNU General Public License as published by the
455 Free Software Foundation; either version 2 of the License, or (at your
456 option) any later version.
457
458 This program is distributed in the hope that it will be useful, but
459 WITHOUT ANY WARRANTY; without even the implied warranty of
460 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
461 General Public License for more details.
462
463 You should have received a copy of the GNU General Public License
464 along with this program; if not, write to the Free Software Foundation,
465 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
466
467
468#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000469static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000470
Eric Andersen85e5e722003-07-22 08:56:55 +0000471#ident "$Id: insmod.c,v 1.99 2003/07/22 08:56:50 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000472
473/* The relocatable object is manipulated using elfin types. */
474
475#include <stdio.h>
476#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000477#include <endian.h>
478
479#if __BYTE_ORDER == __LITTLE_ENDIAN
480#define ELFDATAM ELFDATA2LSB
481#elif __BYTE_ORDER == __BIG_ENDIAN
482#define ELFDATAM ELFDATA2MSB
483#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000484
Eric Andersen9f16d612000-06-12 23:11:16 +0000485#ifndef ElfW
486# if ELFCLASSM == ELFCLASS32
487# define ElfW(x) Elf32_ ## x
488# define ELFW(x) ELF32_ ## x
489# else
490# define ElfW(x) Elf64_ ## x
491# define ELFW(x) ELF64_ ## x
492# endif
493#endif
494
Eric Andersen85e5e722003-07-22 08:56:55 +0000495/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000496#ifndef ELF32_ST_INFO
497# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
498#endif
499
500#ifndef ELF64_ST_INFO
501# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
502#endif
503
504struct obj_string_patch;
505struct obj_symbol_patch;
506
507struct obj_section
508{
509 ElfW(Shdr) header;
510 const char *name;
511 char *contents;
512 struct obj_section *load_next;
513 int idx;
514};
515
516struct obj_symbol
517{
518 struct obj_symbol *next; /* hash table link */
519 const char *name;
520 unsigned long value;
521 unsigned long size;
522 int secidx; /* the defining section index/module */
523 int info;
524 int ksymidx; /* for export to the kernel symtab */
525 int referenced; /* actually used in the link */
526};
527
528/* Hardcode the hash table size. We shouldn't be needing so many
529 symbols that we begin to degrade performance, and we get a big win
530 by giving the compiler a constant divisor. */
531
532#define HASH_BUCKETS 521
533
534struct obj_file
535{
536 ElfW(Ehdr) header;
537 ElfW(Addr) baseaddr;
538 struct obj_section **sections;
539 struct obj_section *load_order;
540 struct obj_section **load_order_search_start;
541 struct obj_string_patch *string_patches;
542 struct obj_symbol_patch *symbol_patches;
543 int (*symbol_cmp)(const char *, const char *);
544 unsigned long (*symbol_hash)(const char *);
545 unsigned long local_symtab_size;
546 struct obj_symbol **local_symtab;
547 struct obj_symbol *symtab[HASH_BUCKETS];
548};
549
550enum obj_reloc
551{
552 obj_reloc_ok,
553 obj_reloc_overflow,
554 obj_reloc_dangerous,
555 obj_reloc_unhandled
556};
557
558struct obj_string_patch
559{
560 struct obj_string_patch *next;
561 int reloc_secidx;
562 ElfW(Addr) reloc_offset;
563 ElfW(Addr) string_offset;
564};
565
566struct obj_symbol_patch
567{
568 struct obj_symbol_patch *next;
569 int reloc_secidx;
570 ElfW(Addr) reloc_offset;
571 struct obj_symbol *sym;
572};
573
574
575/* Generic object manipulation routines. */
576
Eric Andersen044228d2001-07-17 01:12:36 +0000577static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000578
Eric Andersen044228d2001-07-17 01:12:36 +0000579static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000580
Eric Andersen044228d2001-07-17 01:12:36 +0000581static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000582 const char *name);
583
Eric Andersen044228d2001-07-17 01:12:36 +0000584static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000585 struct obj_symbol *sym);
586
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000587#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000588static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000589 int (*cmp)(const char *, const char *),
590 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000591#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000592
Eric Andersen044228d2001-07-17 01:12:36 +0000593static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000594 const char *name);
595
Eric Andersen044228d2001-07-17 01:12:36 +0000596static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000597 struct obj_section *sec);
598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000600 const char *name,
601 unsigned long align,
602 unsigned long size);
603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000605 const char *name,
606 unsigned long align,
607 unsigned long size);
608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000612 const char *string);
613
Eric Andersen6d139642001-12-29 04:15:13 +0000614#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000615static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000616 struct obj_symbol *sym);
Eric Andersen6d139642001-12-29 04:15:13 +0000617#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000618
Eric Andersen044228d2001-07-17 01:12:36 +0000619static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000620
Eric Andersen044228d2001-07-17 01:12:36 +0000621static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000628
Eric Andersen044228d2001-07-17 01:12:36 +0000629static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000630
631/* Architecture specific manipulation routines. */
632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000634
Eric Andersen044228d2001-07-17 01:12:36 +0000635static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000636
Eric Andersen044228d2001-07-17 01:12:36 +0000637static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000640 struct obj_section *targsec,
641 struct obj_section *symsec,
642 struct obj_symbol *sym,
643 ElfW(RelM) *rel, ElfW(Addr) value);
644
Eric Andersencffd5022002-05-24 06:50:15 +0000645static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000646
Eric Andersen6d139642001-12-29 04:15:13 +0000647#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000648static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen6d139642001-12-29 04:15:13 +0000649#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
651#endif /* obj.h */
652//----------------------------------------------------------------------------
653//--------end of modutils obj.h
654//----------------------------------------------------------------------------
655
656
657
Miles Baderae28b042002-04-01 09:34:25 +0000658/* SPFX is always a string, so it can be concatenated to string constants. */
659#ifdef SYMBOL_PREFIX
660#define SPFX SYMBOL_PREFIX
661#else
662#define SPFX ""
663#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000664
Erik Andersen02104321999-12-17 18:57:34 +0000665
Erik Andersend387d011999-12-21 02:55:11 +0000666#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000667static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000668
Eric Andersen9f16d612000-06-12 23:11:16 +0000669/*======================================================================*/
670
Eric Andersen044228d2001-07-17 01:12:36 +0000671static int flag_force_load = 0;
672static int flag_autoclean = 0;
673static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000674static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000675static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000676
677
678/*======================================================================*/
679
Eric Andersencffd5022002-05-24 06:50:15 +0000680#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000681
Eric Andersencffd5022002-05-24 06:50:15 +0000682struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000683{
Eric Andersencffd5022002-05-24 06:50:15 +0000684 struct arch_list_entry *next;
685 CONFIG_LIST_ARCHTYPE addend;
686 int offset;
687 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000688};
Eric Andersencffd5022002-05-24 06:50:15 +0000689
Eric Andersen21adca72000-12-06 18:18:26 +0000690#endif
691
Eric Andersencffd5022002-05-24 06:50:15 +0000692#if defined(CONFIG_USE_SINGLE)
693
694struct arch_single_entry
695{
Eric Andersen9f16d612000-06-12 23:11:16 +0000696 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000697 int inited : 1;
698 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000699};
Eric Andersencffd5022002-05-24 06:50:15 +0000700
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000701#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000702
Eric Andersen2bf658d2001-02-24 20:01:53 +0000703#if defined(__mips__)
704struct mips_hi16
705{
706 struct mips_hi16 *next;
707 Elf32_Addr *addr;
708 Elf32_Addr value;
709};
710#endif
711
Eric Andersenfe4208f2000-09-24 03:44:29 +0000712struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000713 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000714#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000715 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000716#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000717#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000718 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000719#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000720#if defined(__mips__)
721 struct mips_hi16 *mips_hi16_list;
722#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000723};
724
Eric Andersenfe4208f2000-09-24 03:44:29 +0000725struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000726 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000727#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000728#if defined(CONFIG_USE_PLT_LIST)
729 struct arch_list_entry *pltent;
730#else
731 struct arch_single_entry pltent;
732#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000733#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000734#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000735 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000736#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000737};
738
739
Eric Andersen9f16d612000-06-12 23:11:16 +0000740struct external_module {
741 const char *name;
742 ElfW(Addr) addr;
743 int used;
744 size_t nsyms;
745 struct new_module_symbol *syms;
746};
747
Eric Andersen044228d2001-07-17 01:12:36 +0000748static struct new_module_symbol *ksyms;
749static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000750
Eric Andersen044228d2001-07-17 01:12:36 +0000751static struct external_module *ext_modules;
752static int n_ext_modules;
753static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000754extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000755
Eric Andersen61f83052002-06-22 17:15:42 +0000756static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000757static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000758
Eric Andersenfe4208f2000-09-24 03:44:29 +0000759
Erik Andersen02104321999-12-17 18:57:34 +0000760
Eric Andersen9f16d612000-06-12 23:11:16 +0000761/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000762
Eric Andersen9f16d612000-06-12 23:11:16 +0000763
Eric Andersen14d35432001-05-14 17:07:32 +0000764static int check_module_name_match(const char *filename, struct stat *statbuf,
765 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000766{
Eric Andersen14d35432001-05-14 17:07:32 +0000767 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000768
Eric Andersen14d35432001-05-14 17:07:32 +0000769 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000770 return (FALSE);
771 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000772 char *tmp, *tmp1 = bb_xstrdup(filename);
773 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000774 if (strcmp(tmp, fullname) == 0) {
775 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000776 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000777 m_filename = bb_xstrdup(filename);
Eric Andersen14d35432001-05-14 17:07:32 +0000778 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000779 }
Eric Andersen14d35432001-05-14 17:07:32 +0000780 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000781 }
Eric Andersen14d35432001-05-14 17:07:32 +0000782 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000783}
784
Erik Andersen02104321999-12-17 18:57:34 +0000785
Eric Andersen9f16d612000-06-12 23:11:16 +0000786/*======================================================================*/
787
Eric Andersen044228d2001-07-17 01:12:36 +0000788static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000789{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000791 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000792
Eric Andersencffd5022002-05-24 06:50:15 +0000793 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000794
Eric Andersen9f16d612000-06-12 23:11:16 +0000795 return &f->root;
796}
797
Eric Andersen044228d2001-07-17 01:12:36 +0000798static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000799{
800 return xmalloc(sizeof(struct obj_section));
801}
802
Eric Andersen044228d2001-07-17 01:12:36 +0000803static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000804{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000805 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000806 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000807
Eric Andersencffd5022002-05-24 06:50:15 +0000808 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000809
Eric Andersen9f16d612000-06-12 23:11:16 +0000810 return &sym->root;
811}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812
Eric Andersen044228d2001-07-17 01:12:36 +0000813static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000814arch_apply_relocation(struct obj_file *f,
815 struct obj_section *targsec,
816 struct obj_section *symsec,
817 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000818 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000819{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000820 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000821 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000822 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
823 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000824#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
825 struct arch_symbol *isym = (struct arch_symbol *) sym;
826#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000827#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000828 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000829#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000830#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000831 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000832 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000833#if defined(CONFIG_USE_PLT_LIST)
834 struct arch_list_entry *pe;
835#else
836 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000837#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000838#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000839
840 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000841
Eric Andersencffd5022002-05-24 06:50:15 +0000842
843#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000844 case R_ARM_NONE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 break;
846
Eric Andersen21adca72000-12-06 18:18:26 +0000847 case R_ARM_ABS32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000848 *loc += v;
849 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000850
851 case R_ARM_GOT32:
852 goto bb_use_got;
Miles Baderae28b042002-04-01 09:34:25 +0000853
Eric Andersencffd5022002-05-24 06:50:15 +0000854 case R_ARM_GOTPC:
855 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
856 * (which is .got) similar to branch,
857 * but is full 32 bits relative */
858
859 assert(got);
860 *loc += got - dot;
861 break;
862
863 case R_ARM_PC24:
864 case R_ARM_PLT32:
865 goto bb_use_plt;
866
867 case R_ARM_GOTOFF: /* address relative to the got */
868 assert(got);
869 *loc += v - got;
870 break;
871
Eric Andersenbf77f612003-01-23 06:02:39 +0000872#elif defined(__s390__)
873 case R_390_32:
874 *(unsigned int *) loc += v;
875 break;
876 case R_390_16:
877 *(unsigned short *) loc += v;
878 break;
879 case R_390_8:
880 *(unsigned char *) loc += v;
881 break;
882
883 case R_390_PC32:
884 *(unsigned int *) loc += v - dot;
885 break;
886 case R_390_PC16DBL:
887 *(unsigned short *) loc += (v - dot) >> 1;
888 break;
889 case R_390_PC16:
890 *(unsigned short *) loc += v - dot;
891 break;
892
893 case R_390_PLT32:
894 case R_390_PLT16DBL:
895 /* find the plt entry and initialize it. */
896 assert(isym != NULL);
897 pe = (struct arch_single_entry *) &isym->pltent;
898 assert(pe->allocated);
899 if (pe->inited == 0) {
900 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
901 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
902 ip[1] = 0x100607f1;
903 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
904 ip[2] = v - 2;
905 else
906 ip[2] = v;
907 pe->inited = 1;
908 }
909
910 /* Insert relative distance to target. */
911 v = plt + pe->offset - dot;
912 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
913 *(unsigned int *) loc = (unsigned int) v;
914 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
915 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
916 break;
917
918 case R_390_GLOB_DAT:
919 case R_390_JMP_SLOT:
920 *loc = v;
921 break;
922
923 case R_390_RELATIVE:
924 *loc += f->baseaddr;
925 break;
926
927 case R_390_GOTPC:
928 assert(got != 0);
929 *(unsigned long *) loc += got - dot;
930 break;
931
932 case R_390_GOT12:
933 case R_390_GOT16:
934 case R_390_GOT32:
935 assert(isym != NULL);
936 assert(got != 0);
937 if (!isym->gotent.inited)
938 {
939 isym->gotent.inited = 1;
940 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
941 }
942 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
943 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
944 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
945 *(unsigned short *) loc += isym->gotent.offset;
946 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
947 *(unsigned int *) loc += isym->gotent.offset;
948 break;
949
950 case R_390_GOTOFF:
951 assert(got != 0);
952 *loc += v - got;
953 break;
954
Eric Andersencffd5022002-05-24 06:50:15 +0000955#elif defined(__i386__)
956
957 case R_386_NONE:
958 break;
959
960 case R_386_32:
961 *loc += v;
962 break;
963
964 case R_386_PLT32:
965 case R_386_PC32:
966 *loc += v - dot;
967 break;
968
969 case R_386_GLOB_DAT:
970 case R_386_JMP_SLOT:
971 *loc = v;
972 break;
973
974 case R_386_RELATIVE:
975 *loc += f->baseaddr;
976 break;
977
978 case R_386_GOTPC:
979 assert(got != 0);
980 *loc += got - dot;
981 break;
982
983 case R_386_GOT32:
984 goto bb_use_got;
985
986 case R_386_GOTOFF:
987 assert(got != 0);
988 *loc += v - got;
989 break;
990
991#elif defined(__mc68000__)
992
993 case R_68K_NONE:
994 break;
995
996 case R_68K_32:
997 *loc += v;
998 break;
999
1000 case R_68K_8:
1001 if (v > 0xff) {
1002 ret = obj_reloc_overflow;
1003 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00001004 *(char *)loc = v;
1005 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001006
1007 case R_68K_16:
1008 if (v > 0xffff) {
1009 ret = obj_reloc_overflow;
1010 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00001011 *(short *)loc = v;
1012 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001013
Eric Andersencffd5022002-05-24 06:50:15 +00001014 case R_68K_PC8:
1015 v -= dot;
1016 if ((Elf32_Sword)v > 0x7f ||
1017 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1018 ret = obj_reloc_overflow;
1019 }
1020 *(char *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001021 break;
1022
Eric Andersencffd5022002-05-24 06:50:15 +00001023 case R_68K_PC16:
1024 v -= dot;
1025 if ((Elf32_Sword)v > 0x7fff ||
1026 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1027 ret = obj_reloc_overflow;
1028 }
1029 *(short *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001030 break;
1031
Eric Andersencffd5022002-05-24 06:50:15 +00001032 case R_68K_PC32:
1033 *(int *)loc = v - dot;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001034 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001035
Eric Andersencffd5022002-05-24 06:50:15 +00001036 case R_68K_GLOB_DAT:
1037 case R_68K_JMP_SLOT:
1038 *loc = v;
1039 break;
1040
1041 case R_68K_RELATIVE:
1042 *(int *)loc += f->baseaddr;
1043 break;
1044
1045 case R_68K_GOT32:
1046 goto bb_use_got;
1047
1048 case R_68K_GOTOFF:
1049 assert(got != 0);
1050 *loc += v - got;
1051 break;
1052
1053#elif defined(__mips__)
1054
1055 case R_MIPS_NONE:
1056 break;
1057
1058 case R_MIPS_32:
1059 *loc += v;
1060 break;
1061
Eric Andersen2bf658d2001-02-24 20:01:53 +00001062 case R_MIPS_26:
1063 if (v % 4)
1064 ret = obj_reloc_dangerous;
1065 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1066 ret = obj_reloc_overflow;
1067 *loc =
1068 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1069 0x03ffffff);
1070 break;
1071
1072 case R_MIPS_HI16:
1073 {
1074 struct mips_hi16 *n;
1075
1076 /* We cannot relocate this one now because we don't know the value
1077 of the carry we need to add. Save the information, and let LO16
1078 do the actual relocation. */
1079 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1080 n->addr = loc;
1081 n->value = v;
1082 n->next = ifile->mips_hi16_list;
1083 ifile->mips_hi16_list = n;
1084 break;
1085 }
1086
1087 case R_MIPS_LO16:
1088 {
1089 unsigned long insnlo = *loc;
1090 Elf32_Addr val, vallo;
1091
1092 /* Sign extend the addend we extract from the lo insn. */
1093 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1094
1095 if (ifile->mips_hi16_list != NULL) {
1096 struct mips_hi16 *l;
1097
1098 l = ifile->mips_hi16_list;
1099 while (l != NULL) {
1100 struct mips_hi16 *next;
1101 unsigned long insn;
1102
1103 /* The value for the HI16 had best be the same. */
1104 assert(v == l->value);
1105
1106 /* Do the HI16 relocation. Note that we actually don't
1107 need to know anything about the LO16 itself, except where
1108 to find the low 16 bits of the addend needed by the LO16. */
1109 insn = *l->addr;
1110 val =
1111 ((insn & 0xffff) << 16) +
1112 vallo;
1113 val += v;
1114
1115 /* Account for the sign extension that will happen in the
1116 low bits. */
1117 val =
1118 ((val >> 16) +
1119 ((val & 0x8000) !=
1120 0)) & 0xffff;
1121
1122 insn = (insn & ~0xffff) | val;
1123 *l->addr = insn;
1124
1125 next = l->next;
1126 free(l);
1127 l = next;
1128 }
1129
1130 ifile->mips_hi16_list = NULL;
1131 }
1132
1133 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1134 val = v + vallo;
1135 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1136 *loc = insnlo;
1137 break;
1138 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001139
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001140#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001141
1142 case R_PPC_ADDR16_HA:
1143 *(unsigned short *)loc = (v + 0x8000) >> 16;
1144 break;
1145
1146 case R_PPC_ADDR16_HI:
1147 *(unsigned short *)loc = v >> 16;
1148 break;
1149
1150 case R_PPC_ADDR16_LO:
1151 *(unsigned short *)loc = v;
1152 break;
1153
1154 case R_PPC_REL24:
1155 goto bb_use_plt;
1156
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001157 case R_PPC_REL32:
1158 *loc = v - dot;
1159 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001160
1161 case R_PPC_ADDR32:
1162 *loc = v;
1163 break;
1164
1165#elif defined(__sh__)
1166
1167 case R_SH_NONE:
1168 break;
1169
1170 case R_SH_DIR32:
1171 *loc += v;
1172 break;
1173
1174 case R_SH_REL32:
1175 *loc += v - dot;
1176 break;
1177
1178 case R_SH_PLT32:
1179 *loc = v - dot;
1180 break;
1181
1182 case R_SH_GLOB_DAT:
1183 case R_SH_JMP_SLOT:
1184 *loc = v;
1185 break;
1186
1187 case R_SH_RELATIVE:
1188 *loc = f->baseaddr + rel->r_addend;
1189 break;
1190
1191 case R_SH_GOTPC:
1192 assert(got != 0);
1193 *loc = got - dot + rel->r_addend;
1194 break;
1195
1196 case R_SH_GOT32:
1197 goto bb_use_got;
1198
1199 case R_SH_GOTOFF:
1200 assert(got != 0);
1201 *loc = v - got;
1202 break;
1203
Eric Andersen21adca72000-12-06 18:18:26 +00001204#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001205
Eric Andersencffd5022002-05-24 06:50:15 +00001206 default:
1207 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1208 ret = obj_reloc_unhandled;
1209 break;
1210
1211#if defined (__v850e__)
1212 case R_V850_NONE:
1213 break;
1214
1215 case R_V850_32:
1216 /* We write two shorts instead of a long because even
1217 32-bit insns only need half-word alignment, but
1218 32-bit data needs to be long-word aligned. */
1219 v += ((unsigned short *)loc)[0];
1220 v += ((unsigned short *)loc)[1] << 16;
1221 ((unsigned short *)loc)[0] = v & 0xffff;
1222 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1223 break;
1224
1225 case R_V850_22_PCREL:
1226 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001227#endif
1228
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001229#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001230
Eric Andersencffd5022002-05-24 06:50:15 +00001231 bb_use_plt:
1232
Eric Andersen21adca72000-12-06 18:18:26 +00001233 /* find the plt entry and initialize it if necessary */
1234 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001235
Eric Andersencffd5022002-05-24 06:50:15 +00001236#if defined(CONFIG_USE_PLT_LIST)
1237 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1238 pe = pe->next;
1239 assert(pe != NULL);
1240#else
1241 pe = &isym->pltent;
1242#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001243
Eric Andersen21adca72000-12-06 18:18:26 +00001244 if (! pe->inited) {
1245 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001246
1247 /* generate some machine code */
1248
1249#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001250 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1251 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001252#endif
1253#if defined(__powerpc__)
1254 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1255 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1256 ip[2] = 0x7d6903a6; /* mtctr r11 */
1257 ip[3] = 0x4e800420; /* bctr */
1258#endif
Miles Baderae28b042002-04-01 09:34:25 +00001259#if defined (__v850e__)
1260 /* We have to trash a register, so we assume that any control
1261 transfer more than 21-bits away must be a function call
1262 (so we can use a call-clobbered register). */
1263 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1264 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
1265#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001266 pe->inited = 1;
1267 }
1268
1269 /* relative distance to target */
1270 v -= dot;
1271 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001272#if defined (__arm__) || defined (__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001273 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001274#elif defined (__v850e__)
1275 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
1276#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001277 /* go via the plt */
1278 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001279
1280#if defined (__v850e__)
1281 if (v & 1)
1282#else
Eric Andersen21adca72000-12-06 18:18:26 +00001283 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001284#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001285 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001286
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001287 /* merge the offset into the instruction. */
1288#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001289 /* Convert to words. */
1290 v >>= 2;
1291
Eric Andersen21adca72000-12-06 18:18:26 +00001292 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001293#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001294#if defined(__powerpc__)
1295 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1296#endif
Miles Baderae28b042002-04-01 09:34:25 +00001297#if defined (__v850e__)
1298 /* We write two shorts instead of a long because even 32-bit insns
1299 only need half-word alignment, but the 32-bit data write needs
1300 to be long-word aligned. */
1301 ((unsigned short *)loc)[0] =
1302 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1303 | ((v >> 16) & 0x3f); /* offs high part */
1304 ((unsigned short *)loc)[1] =
1305 (v & 0xffff); /* offs low part */
1306#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001307 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001308#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001309
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001310#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001311 bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001312
Eric Andersen9f16d612000-06-12 23:11:16 +00001313 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001314 /* needs an entry in the .got: set it, once */
Eric Andersencffd5022002-05-24 06:50:15 +00001315 if (!isym->gotent.inited) {
1316 isym->gotent.inited = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001317 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001318 }
Eric Andersen21adca72000-12-06 18:18:26 +00001319 /* make the reloc with_respect_to_.got */
1320#if defined(__sh__)
1321 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001322#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001323 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001324#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001325 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001326
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001327#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001328 }
1329
1330 return ret;
1331}
1332
Eric Andersencffd5022002-05-24 06:50:15 +00001333
1334#if defined(CONFIG_USE_LIST)
1335
1336static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1337 int offset, int size)
1338{
1339 struct arch_list_entry *pe;
1340
1341 for (pe = *list; pe != NULL; pe = pe->next) {
1342 if (pe->addend == rel->r_addend) {
1343 break;
1344 }
1345 }
1346
1347 if (pe == NULL) {
1348 pe = xmalloc(sizeof(struct arch_list_entry));
1349 pe->next = *list;
1350 pe->addend = rel->r_addend;
1351 pe->offset = offset;
1352 pe->inited = 0;
1353 *list = pe;
1354 return size;
1355 }
1356 return 0;
1357}
1358
1359#endif
1360
1361#if defined(CONFIG_USE_SINGLE)
1362
1363static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1364 int offset, int size)
1365{
1366 if (single->allocated == 0) {
1367 single->allocated = 1;
1368 single->offset = offset;
1369 single->inited = 0;
1370 return size;
1371 }
1372 return 0;
1373}
1374
1375#endif
1376
1377#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1378
1379static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
1380 int offset, int size)
1381{
1382 struct obj_section *myrelsec = obj_find_section(f, name);
1383
1384 if (offset == 0) {
1385 offset += size;
1386 }
1387
1388 if (myrelsec) {
1389 obj_extend_section(myrelsec, offset);
1390 } else {
1391 myrelsec = obj_create_alloced_section(f, name,
1392 size, offset);
1393 assert(myrelsec);
1394 }
1395
1396 return myrelsec;
1397}
1398
1399#endif
1400
1401static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001402{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001403#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001404 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001405 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001406#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001407 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001408#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001409#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001410 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001411#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001412 struct obj_section *relsec, *symsec, *strsec;
1413 ElfW(RelM) *rel, *relend;
1414 ElfW(Sym) *symtab, *extsym;
1415 const char *strtab, *name;
1416 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001417
Eric Andersen21adca72000-12-06 18:18:26 +00001418 for (i = 0; i < f->header.e_shnum; ++i) {
1419 relsec = f->sections[i];
1420 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001421 continue;
1422
Eric Andersen21adca72000-12-06 18:18:26 +00001423 symsec = f->sections[relsec->header.sh_link];
1424 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001425
Eric Andersen21adca72000-12-06 18:18:26 +00001426 rel = (ElfW(RelM) *) relsec->contents;
1427 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1428 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001429 strtab = (const char *) strsec->contents;
1430
1431 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001432 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001433
Eric Andersencffd5022002-05-24 06:50:15 +00001434#if defined(CONFIG_USE_GOT_ENTRIES)
1435 got_allocate = 0;
1436#endif
1437#if defined(CONFIG_USE_PLT_ENTRIES)
1438 plt_allocate = 0;
1439#endif
1440
Eric Andersen9f16d612000-06-12 23:11:16 +00001441 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001442#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001443 case R_ARM_PC24:
1444 case R_ARM_PLT32:
Eric Andersencffd5022002-05-24 06:50:15 +00001445 plt_allocate = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001446 break;
1447
Eric Andersen21adca72000-12-06 18:18:26 +00001448 case R_ARM_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001449 case R_ARM_GOTPC:
1450 got_needed = 1;
1451 continue;
1452
1453 case R_ARM_GOT32:
1454 got_allocate = 1;
1455 break;
1456
Eric Andersen21adca72000-12-06 18:18:26 +00001457#elif defined(__i386__)
1458 case R_386_GOTPC:
1459 case R_386_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001460 got_needed = 1;
1461 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001462
Eric Andersencffd5022002-05-24 06:50:15 +00001463 case R_386_GOT32:
1464 got_allocate = 1;
1465 break;
1466
1467#elif defined(__powerpc__)
1468 case R_PPC_REL24:
1469 plt_allocate = 1;
1470 break;
1471
1472#elif defined(__mc68000__)
1473 case R_68K_GOT32:
1474 got_allocate = 1;
1475 break;
1476
1477 case R_68K_GOTOFF:
1478 got_needed = 1;
1479 continue;
1480
1481#elif defined(__sh__)
1482 case R_SH_GOT32:
1483 got_allocate = 1;
1484 break;
1485
1486 case R_SH_GOTPC:
1487 case R_SH_GOTOFF:
1488 got_needed = 1;
1489 continue;
1490
1491#elif defined (__v850e__)
1492 case R_V850_22_PCREL:
1493 plt_needed = 1;
1494 break;
1495
1496#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001497 default:
1498 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001499 }
1500
Eric Andersen21adca72000-12-06 18:18:26 +00001501 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001502 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001503 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001504 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001505 }
1506 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001507#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001508 if (got_allocate) {
1509 got_offset += arch_single_init(
1510 rel, &intsym->gotent,
1511 got_offset, CONFIG_GOT_ENTRY_SIZE);
1512
1513 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001514 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001515#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001516#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001517 if (plt_allocate) {
1518#if defined(CONFIG_USE_PLT_LIST)
1519 plt_offset += arch_list_add(
1520 rel, &intsym->pltent,
1521 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1522#else
1523 plt_offset += arch_single_init(
1524 rel, &intsym->pltent,
1525 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1526#endif
1527 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001528 }
1529#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001530 }
Miles Baderae28b042002-04-01 09:34:25 +00001531 }
Eric Andersen21adca72000-12-06 18:18:26 +00001532
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001533#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001534 if (got_needed) {
1535 ifile->got = arch_xsect_init(f, ".got", got_offset,
1536 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001537 }
Eric Andersen21adca72000-12-06 18:18:26 +00001538#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001539
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001540#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001541 if (plt_needed) {
1542 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
1543 CONFIG_PLT_ENTRY_SIZE);
1544 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001545#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001546
1547#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001548}
1549
Eric Andersen6d139642001-12-29 04:15:13 +00001550#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00001551static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001552{
1553 return 1;
1554}
Eric Andersen6d139642001-12-29 04:15:13 +00001555#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001556
1557/*======================================================================*/
1558
1559/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001560static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001561{
1562 unsigned long h = 0;
1563 unsigned long g;
1564 unsigned char ch;
1565
1566 while (n > 0) {
1567 ch = *name++;
1568 h = (h << 4) + ch;
1569 if ((g = (h & 0xf0000000)) != 0) {
1570 h ^= g >> 24;
1571 h &= ~g;
1572 }
1573 n--;
1574 }
1575 return h;
1576}
1577
Eric Andersen044228d2001-07-17 01:12:36 +00001578static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001579{
1580 return obj_elf_hash_n(name, strlen(name));
1581}
1582
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001583#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001584/* String comparison for non-co-versioned kernel and module. */
1585
1586static int ncv_strcmp(const char *a, const char *b)
1587{
1588 size_t alen = strlen(a), blen = strlen(b);
1589
1590 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1591 return strncmp(a, b, alen);
1592 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1593 return strncmp(a, b, blen);
1594 else
1595 return strcmp(a, b);
1596}
1597
1598/* String hashing for non-co-versioned kernel and module. Here
1599 we are simply forced to drop the crc from the hash. */
1600
1601static unsigned long ncv_symbol_hash(const char *str)
1602{
1603 size_t len = strlen(str);
1604 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1605 len -= 10;
1606 return obj_elf_hash_n(str, len);
1607}
1608
Eric Andersen044228d2001-07-17 01:12:36 +00001609static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001610obj_set_symbol_compare(struct obj_file *f,
1611 int (*cmp) (const char *, const char *),
1612 unsigned long (*hash) (const char *))
1613{
1614 if (cmp)
1615 f->symbol_cmp = cmp;
1616 if (hash) {
1617 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1618 int i;
1619
1620 f->symbol_hash = hash;
1621
1622 memcpy(tmptab, f->symtab, sizeof(tmptab));
1623 memset(f->symtab, 0, sizeof(f->symtab));
1624
1625 for (i = 0; i < HASH_BUCKETS; ++i)
1626 for (sym = tmptab[i]; sym; sym = next) {
1627 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1628 next = sym->next;
1629 sym->next = f->symtab[h];
1630 f->symtab[h] = sym;
1631 }
1632 }
1633}
1634
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001635#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001636
Eric Andersen044228d2001-07-17 01:12:36 +00001637static struct obj_symbol *
1638obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001639 unsigned long symidx, int info,
1640 int secidx, ElfW(Addr) value,
1641 unsigned long size)
1642{
1643 struct obj_symbol *sym;
1644 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1645 int n_type = ELFW(ST_TYPE) (info);
1646 int n_binding = ELFW(ST_BIND) (info);
1647
1648 for (sym = f->symtab[hash]; sym; sym = sym->next)
1649 if (f->symbol_cmp(sym->name, name) == 0) {
1650 int o_secidx = sym->secidx;
1651 int o_info = sym->info;
1652 int o_type = ELFW(ST_TYPE) (o_info);
1653 int o_binding = ELFW(ST_BIND) (o_info);
1654
1655 /* A redefinition! Is it legal? */
1656
1657 if (secidx == SHN_UNDEF)
1658 return sym;
1659 else if (o_secidx == SHN_UNDEF)
1660 goto found;
1661 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1662 /* Cope with local and global symbols of the same name
1663 in the same object file, as might have been created
1664 by ld -r. The only reason locals are now seen at this
1665 level at all is so that we can do semi-sensible things
1666 with parameters. */
1667
1668 struct obj_symbol *nsym, **p;
1669
1670 nsym = arch_new_symbol();
1671 nsym->next = sym->next;
1672 nsym->ksymidx = -1;
1673
1674 /* Excise the old (local) symbol from the hash chain. */
1675 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1676 continue;
1677 *p = sym = nsym;
1678 goto found;
1679 } else if (n_binding == STB_LOCAL) {
1680 /* Another symbol of the same name has already been defined.
1681 Just add this to the local table. */
1682 sym = arch_new_symbol();
1683 sym->next = NULL;
1684 sym->ksymidx = -1;
1685 f->local_symtab[symidx] = sym;
1686 goto found;
1687 } else if (n_binding == STB_WEAK)
1688 return sym;
1689 else if (o_binding == STB_WEAK)
1690 goto found;
1691 /* Don't unify COMMON symbols with object types the programmer
1692 doesn't expect. */
1693 else if (secidx == SHN_COMMON
1694 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1695 return sym;
1696 else if (o_secidx == SHN_COMMON
1697 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1698 goto found;
1699 else {
1700 /* Don't report an error if the symbol is coming from
1701 the kernel or some external module. */
1702 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001703 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001704 return sym;
1705 }
1706 }
1707
1708 /* Completely new symbol. */
1709 sym = arch_new_symbol();
1710 sym->next = f->symtab[hash];
1711 f->symtab[hash] = sym;
1712 sym->ksymidx = -1;
1713
Eric Andersen66ca9482001-06-28 21:36:06 +00001714 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1715 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001716 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001717 name, (long) symidx, (long) f->local_symtab_size);
1718 else
1719 f->local_symtab[symidx] = sym;
1720 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001721
1722 found:
1723 sym->name = name;
1724 sym->value = value;
1725 sym->size = size;
1726 sym->secidx = secidx;
1727 sym->info = info;
1728
1729 return sym;
1730}
1731
Eric Andersen044228d2001-07-17 01:12:36 +00001732static struct obj_symbol *
1733obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001734{
1735 struct obj_symbol *sym;
1736 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1737
1738 for (sym = f->symtab[hash]; sym; sym = sym->next)
1739 if (f->symbol_cmp(sym->name, name) == 0)
1740 return sym;
1741
1742 return NULL;
1743}
1744
Eric Andersen044228d2001-07-17 01:12:36 +00001745static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001746 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1747{
1748 if (sym) {
1749 if (sym->secidx >= SHN_LORESERVE)
1750 return sym->value;
1751
1752 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1753 } else {
1754 /* As a special case, a NULL sym has value zero. */
1755 return 0;
1756 }
1757}
1758
Eric Andersen044228d2001-07-17 01:12:36 +00001759static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001760{
1761 int i, n = f->header.e_shnum;
1762
1763 for (i = 0; i < n; ++i)
1764 if (strcmp(f->sections[i]->name, name) == 0)
1765 return f->sections[i];
1766
1767 return NULL;
1768}
1769
1770static int obj_load_order_prio(struct obj_section *a)
1771{
1772 unsigned long af, ac;
1773
1774 af = a->header.sh_flags;
1775
1776 ac = 0;
1777 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1778 strcmp(a->name + 5, ".init"))
1779 ac |= 32;
1780 if (af & SHF_ALLOC)
1781 ac |= 16;
1782 if (!(af & SHF_WRITE))
1783 ac |= 8;
1784 if (af & SHF_EXECINSTR)
1785 ac |= 4;
1786 if (a->header.sh_type != SHT_NOBITS)
1787 ac |= 2;
1788
1789 return ac;
1790}
1791
Eric Andersen044228d2001-07-17 01:12:36 +00001792static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001793obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1794{
1795 struct obj_section **p;
1796 int prio = obj_load_order_prio(sec);
1797 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1798 if (obj_load_order_prio(*p) < prio)
1799 break;
1800 sec->load_next = *p;
1801 *p = sec;
1802}
1803
Eric Andersen044228d2001-07-17 01:12:36 +00001804static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001805 const char *name,
1806 unsigned long align,
1807 unsigned long size)
1808{
1809 int newidx = f->header.e_shnum++;
1810 struct obj_section *sec;
1811
1812 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1813 f->sections[newidx] = sec = arch_new_section();
1814
1815 memset(sec, 0, sizeof(*sec));
1816 sec->header.sh_type = SHT_PROGBITS;
1817 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1818 sec->header.sh_size = size;
1819 sec->header.sh_addralign = align;
1820 sec->name = name;
1821 sec->idx = newidx;
1822 if (size)
1823 sec->contents = xmalloc(size);
1824
1825 obj_insert_section_load_order(f, sec);
1826
1827 return sec;
1828}
1829
Eric Andersen044228d2001-07-17 01:12:36 +00001830static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001831 const char *name,
1832 unsigned long align,
1833 unsigned long size)
1834{
1835 int newidx = f->header.e_shnum++;
1836 struct obj_section *sec;
1837
1838 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1839 f->sections[newidx] = sec = arch_new_section();
1840
1841 memset(sec, 0, sizeof(*sec));
1842 sec->header.sh_type = SHT_PROGBITS;
1843 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1844 sec->header.sh_size = size;
1845 sec->header.sh_addralign = align;
1846 sec->name = name;
1847 sec->idx = newidx;
1848 if (size)
1849 sec->contents = xmalloc(size);
1850
1851 sec->load_next = f->load_order;
1852 f->load_order = sec;
1853 if (f->load_order_search_start == &f->load_order)
1854 f->load_order_search_start = &sec->load_next;
1855
1856 return sec;
1857}
1858
Eric Andersen044228d2001-07-17 01:12:36 +00001859static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001860{
1861 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001862 if (more) {
1863 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1864 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001865 return sec->contents + oldsize;
1866}
1867
1868
Eric Andersen9f16d612000-06-12 23:11:16 +00001869/* Conditionally add the symbols from the given symbol set to the
1870 new module. */
1871
1872static int
1873add_symbols_from(
1874 struct obj_file *f,
1875 int idx, struct new_module_symbol *syms, size_t nsyms)
1876{
1877 struct new_module_symbol *s;
1878 size_t i;
1879 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001880#ifdef SYMBOL_PREFIX
1881 char *name_buf = 0;
1882 size_t name_alloced_size = 0;
1883#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001884
1885 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001886 /* Only add symbols that are already marked external.
1887 If we override locals we may cause problems for
1888 argument initialization. We will also create a false
1889 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001890 struct obj_symbol *sym;
Miles Baderae28b042002-04-01 09:34:25 +00001891 char *name = (char *)s->name;
Eric Andersen9f16d612000-06-12 23:11:16 +00001892
Miles Baderae28b042002-04-01 09:34:25 +00001893#ifdef SYMBOL_PREFIX
1894 /* Prepend SYMBOL_PREFIX to the symbol's name (the
1895 kernel exports `C names', but module object files
1896 reference `linker names'). */
1897 size_t extra = sizeof SYMBOL_PREFIX;
1898 size_t name_size = strlen (name) + extra;
1899 if (name_size > name_alloced_size) {
1900 name_alloced_size = name_size * 2;
1901 name_buf = alloca (name_alloced_size);
1902 }
1903 strcpy (name_buf, SYMBOL_PREFIX);
1904 strcpy (name_buf + extra - 1, name);
1905 name = name_buf;
1906#endif /* SYMBOL_PREFIX */
1907
1908 sym = obj_find_symbol(f, name);
1909 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
1910#ifdef SYMBOL_PREFIX
1911 /* Put NAME_BUF into more permanent storage. */
1912 name = xmalloc (name_size);
1913 strcpy (name, name_buf);
1914#endif
1915 sym = obj_add_symbol(f, name, -1,
1916 ELFW(ST_INFO) (STB_GLOBAL,
1917 STT_NOTYPE),
1918 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00001919 /* Did our symbol just get installed? If so, mark the
1920 module as "used". */
1921 if (sym->secidx == idx)
1922 used = 1;
1923 }
1924 }
1925
1926 return used;
1927}
1928
1929static void add_kernel_symbols(struct obj_file *f)
1930{
1931 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001932 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001933
1934 /* Add module symbols first. */
1935
1936 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1937 if (m->nsyms
1938 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1939 m->nsyms)) m->used = 1, ++nused;
1940
1941 n_ext_modules_used = nused;
1942
1943 /* And finally the symbols from the kernel proper. */
1944
1945 if (nksyms)
1946 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1947}
1948
1949static char *get_modinfo_value(struct obj_file *f, const char *key)
1950{
1951 struct obj_section *sec;
1952 char *p, *v, *n, *ep;
1953 size_t klen = strlen(key);
1954
1955 sec = obj_find_section(f, ".modinfo");
1956 if (sec == NULL)
1957 return NULL;
1958 p = sec->contents;
1959 ep = p + sec->header.sh_size;
1960 while (p < ep) {
1961 v = strchr(p, '=');
1962 n = strchr(p, '\0');
1963 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001964 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001965 return v + 1;
1966 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001967 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001968 return n;
1969 }
1970 p = n + 1;
1971 }
1972
1973 return NULL;
1974}
1975
1976
1977/*======================================================================*/
1978/* Functions relating to module loading in pre 2.1 kernels. */
1979
1980static int
1981old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1982{
1983 while (argc > 0) {
1984 char *p, *q;
1985 struct obj_symbol *sym;
1986 int *loc;
1987
1988 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001989 if ((q = strchr(p, '=')) == NULL) {
1990 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001991 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001992 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001993 *q++ = '\0';
1994
1995 sym = obj_find_symbol(f, p);
1996
1997 /* Also check that the parameter was not resolved from the kernel. */
1998 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001999 bb_error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002000 return 0;
2001 }
2002
2003 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
2004
2005 /* Do C quoting if we begin with a ". */
2006 if (*q == '"') {
2007 char *r, *str;
2008
2009 str = alloca(strlen(q));
2010 for (r = str, q++; *q != '"'; ++q, ++r) {
2011 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002012 bb_error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002013 return 0;
2014 } else if (*q == '\\')
2015 switch (*++q) {
2016 case 'a':
2017 *r = '\a';
2018 break;
2019 case 'b':
2020 *r = '\b';
2021 break;
2022 case 'e':
2023 *r = '\033';
2024 break;
2025 case 'f':
2026 *r = '\f';
2027 break;
2028 case 'n':
2029 *r = '\n';
2030 break;
2031 case 'r':
2032 *r = '\r';
2033 break;
2034 case 't':
2035 *r = '\t';
2036 break;
2037
2038 case '0':
2039 case '1':
2040 case '2':
2041 case '3':
2042 case '4':
2043 case '5':
2044 case '6':
2045 case '7':
2046 {
2047 int c = *q - '0';
2048 if (q[1] >= '0' && q[1] <= '7') {
2049 c = (c * 8) + *++q - '0';
2050 if (q[1] >= '0' && q[1] <= '7')
2051 c = (c * 8) + *++q - '0';
2052 }
2053 *r = c;
2054 }
2055 break;
2056
2057 default:
2058 *r = *q;
2059 break;
2060 } else
2061 *r = *q;
2062 }
2063 *r = '\0';
2064 obj_string_patch(f, sym->secidx, sym->value, str);
2065 } else if (*q >= '0' && *q <= '9') {
2066 do
2067 *loc++ = strtoul(q, &q, 0);
2068 while (*q++ == ',');
2069 } else {
2070 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00002071 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002072 char *r; /* To search for commas */
2073
2074 /* Break the string with comas */
2075 while ((r = strchr(q, ',')) != (char *) NULL) {
2076 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00002077 obj_string_patch(f, sym->secidx, myloc - contents, q);
2078 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00002079 q = r;
2080 }
2081
2082 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00002083 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00002084 }
2085
2086 argc--, argv++;
2087 }
2088
2089 return 1;
2090}
2091
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002092#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002093static int old_is_module_checksummed(struct obj_file *f)
2094{
2095 return obj_find_symbol(f, "Using_Versions") != NULL;
2096}
2097/* Get the module's kernel version in the canonical integer form. */
2098
2099static int
2100old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2101{
2102 struct obj_symbol *sym;
2103 char *p, *q;
2104 int a, b, c;
2105
2106 sym = obj_find_symbol(f, "kernel_version");
2107 if (sym == NULL)
2108 return -1;
2109
2110 p = f->sections[sym->secidx]->contents + sym->value;
Eric Andersen2d342152002-06-18 05:16:25 +00002111 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002112
2113 a = strtoul(p, &p, 10);
2114 if (*p != '.')
2115 return -1;
2116 b = strtoul(p + 1, &p, 10);
2117 if (*p != '.')
2118 return -1;
2119 c = strtoul(p + 1, &q, 10);
2120 if (p + 1 == q)
2121 return -1;
2122
2123 return a << 16 | b << 8 | c;
2124}
2125
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002126#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002127
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002128#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002129
2130/* Fetch all the symbols and divvy them up as appropriate for the modules. */
2131
Eric Andersen8c185f92000-09-22 00:38:07 +00002132static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002133{
2134 struct old_kernel_sym *ks, *k;
2135 struct new_module_symbol *s;
2136 struct external_module *mod;
2137 int nks, nms, nmod, i;
2138
2139 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00002140 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002141 if (nks)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002142 bb_perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002143 else
Manuel Novoa III cad53642003-03-19 09:13:01 +00002144 bb_error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00002145 return 0;
2146 }
2147
2148 ks = k = xmalloc(nks * sizeof(*ks));
2149
2150 if (get_kernel_syms(ks) != nks) {
2151 perror("inconsistency with get_kernel_syms -- is someone else "
2152 "playing with modules?");
2153 free(ks);
2154 return 0;
2155 }
2156
2157 /* Collect the module information. */
2158
2159 mod = NULL;
2160 nmod = -1;
2161
2162 while (k->name[0] == '#' && k->name[1]) {
2163 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00002164
2165 /* Find out how many symbols this module has. */
2166 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
2167 continue;
2168 nms = k2 - k - 1;
2169
2170 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
2171 mod[nmod].name = k->name + 1;
2172 mod[nmod].addr = k->value;
2173 mod[nmod].used = 0;
2174 mod[nmod].nsyms = nms;
2175 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2176
2177 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
2178 s->name = (unsigned long) k->name;
2179 s->value = k->value;
2180 }
2181
2182 k = k2;
2183 }
2184
2185 ext_modules = mod;
2186 n_ext_modules = nmod + 1;
2187
2188 /* Now collect the symbols for the kernel proper. */
2189
2190 if (k->name[0] == '#')
2191 ++k;
2192
2193 nksyms = nms = nks - (k - ks);
2194 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2195
2196 for (i = 0; i < nms; ++i, ++s, ++k) {
2197 s->name = (unsigned long) k->name;
2198 s->value = k->value;
2199 }
2200
2201 return 1;
2202}
2203
2204/* Return the kernel symbol checksum version, or zero if not used. */
2205
2206static int old_is_kernel_checksummed(void)
2207{
2208 /* Using_Versions is the first symbol. */
2209 if (nksyms > 0
2210 && strcmp((char *) ksyms[0].name,
2211 "Using_Versions") == 0) return ksyms[0].value;
2212 else
2213 return 0;
2214}
2215
2216
2217static int old_create_mod_use_count(struct obj_file *f)
2218{
2219 struct obj_section *sec;
2220
2221 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
2222 sizeof(long));
2223
2224 obj_add_symbol(f, "mod_use_count_", -1,
2225 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2226 sizeof(long));
2227
2228 return 1;
2229}
2230
2231static int
2232old_init_module(const char *m_name, struct obj_file *f,
2233 unsigned long m_size)
2234{
2235 char *image;
2236 struct old_mod_routines routines;
2237 struct old_symbol_table *symtab;
2238 int ret;
2239
2240 /* Create the symbol table */
2241 {
2242 int nsyms = 0, strsize = 0, total;
2243
2244 /* Size things first... */
2245 if (flag_export) {
2246 int i;
2247 for (i = 0; i < HASH_BUCKETS; ++i) {
2248 struct obj_symbol *sym;
2249 for (sym = f->symtab[i]; sym; sym = sym->next)
2250 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2251 && sym->secidx <= SHN_HIRESERVE)
2252 {
2253 sym->ksymidx = nsyms++;
2254 strsize += strlen(sym->name) + 1;
2255 }
2256 }
2257 }
2258
2259 total = (sizeof(struct old_symbol_table)
2260 + nsyms * sizeof(struct old_module_symbol)
2261 + n_ext_modules_used * sizeof(struct old_module_ref)
2262 + strsize);
2263 symtab = xmalloc(total);
2264 symtab->size = total;
2265 symtab->n_symbols = nsyms;
2266 symtab->n_refs = n_ext_modules_used;
2267
2268 if (flag_export && nsyms) {
2269 struct old_module_symbol *ksym;
2270 char *str;
2271 int i;
2272
2273 ksym = symtab->symbol;
2274 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
2275 + n_ext_modules_used * sizeof(struct old_module_ref));
2276
2277 for (i = 0; i < HASH_BUCKETS; ++i) {
2278 struct obj_symbol *sym;
2279 for (sym = f->symtab[i]; sym; sym = sym->next)
2280 if (sym->ksymidx >= 0) {
2281 ksym->addr = obj_symbol_final_value(f, sym);
2282 ksym->name =
2283 (unsigned long) str - (unsigned long) symtab;
2284
Matt Kraai70a78552001-01-04 02:00:17 +00002285 strcpy(str, sym->name);
2286 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002287 ksym++;
2288 }
2289 }
2290 }
2291
2292 if (n_ext_modules_used) {
2293 struct old_module_ref *ref;
2294 int i;
2295
2296 ref = (struct old_module_ref *)
2297 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2298
2299 for (i = 0; i < n_ext_modules; ++i)
2300 if (ext_modules[i].used)
2301 ref++->module = ext_modules[i].addr;
2302 }
2303 }
2304
2305 /* Fill in routines. */
2306
2307 routines.init =
Miles Baderae28b042002-04-01 09:34:25 +00002308 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002309 routines.cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002310 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002311
2312 /* Whew! All of the initialization is complete. Collect the final
2313 module image and give it to the kernel. */
2314
2315 image = xmalloc(m_size);
2316 obj_create_image(f, image);
2317
2318 /* image holds the complete relocated module, accounting correctly for
2319 mod_use_count. However the old module kernel support assume that
2320 it is receiving something which does not contain mod_use_count. */
2321 ret = old_sys_init_module(m_name, image + sizeof(long),
2322 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2323 : 0), &routines, symtab);
2324 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002325 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002326
2327 free(image);
2328 free(symtab);
2329
2330 return ret == 0;
2331}
2332
2333#else
2334
2335#define old_create_mod_use_count(x) TRUE
2336#define old_init_module(x, y, z) TRUE
2337
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002338#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002339
2340
2341
2342/*======================================================================*/
2343/* Functions relating to module loading after 2.1.18. */
2344
2345static int
2346new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2347{
2348 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002349 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002350 struct obj_symbol *sym;
2351 char *contents, *loc;
2352 int min, max, n;
2353
2354 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002355 if ((q = strchr(p, '=')) == NULL) {
2356 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002357 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002358 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002359
2360 key = alloca(q - p + 6);
2361 memcpy(key, "parm_", 5);
2362 memcpy(key + 5, p, q - p);
2363 key[q - p + 5] = 0;
2364
2365 p = get_modinfo_value(f, key);
2366 key += 5;
2367 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002368 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002369 return 0;
2370 }
2371
Miles Baderae28b042002-04-01 09:34:25 +00002372#ifdef SYMBOL_PREFIX
2373 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2374 strcpy (sym_name, SYMBOL_PREFIX);
2375 strcat (sym_name, key);
2376#else
2377 sym_name = key;
2378#endif
2379 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002380
2381 /* Also check that the parameter was not resolved from the kernel. */
2382 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002383 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002384 return 0;
2385 }
2386
2387 if (isdigit(*p)) {
2388 min = strtoul(p, &p, 10);
2389 if (*p == '-')
2390 max = strtoul(p + 1, &p, 10);
2391 else
2392 max = min;
2393 } else
2394 min = max = 1;
2395
2396 contents = f->sections[sym->secidx]->contents;
2397 loc = contents + sym->value;
2398 n = (*++q != '\0');
2399
2400 while (1) {
2401 if ((*p == 's') || (*p == 'c')) {
2402 char *str;
2403
2404 /* Do C quoting if we begin with a ", else slurp the lot. */
2405 if (*q == '"') {
2406 char *r;
2407
2408 str = alloca(strlen(q));
2409 for (r = str, q++; *q != '"'; ++q, ++r) {
2410 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002411 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002412 key);
2413 return 0;
2414 } else if (*q == '\\')
2415 switch (*++q) {
2416 case 'a':
2417 *r = '\a';
2418 break;
2419 case 'b':
2420 *r = '\b';
2421 break;
2422 case 'e':
2423 *r = '\033';
2424 break;
2425 case 'f':
2426 *r = '\f';
2427 break;
2428 case 'n':
2429 *r = '\n';
2430 break;
2431 case 'r':
2432 *r = '\r';
2433 break;
2434 case 't':
2435 *r = '\t';
2436 break;
2437
2438 case '0':
2439 case '1':
2440 case '2':
2441 case '3':
2442 case '4':
2443 case '5':
2444 case '6':
2445 case '7':
2446 {
2447 int c = *q - '0';
2448 if (q[1] >= '0' && q[1] <= '7') {
2449 c = (c * 8) + *++q - '0';
2450 if (q[1] >= '0' && q[1] <= '7')
2451 c = (c * 8) + *++q - '0';
2452 }
2453 *r = c;
2454 }
2455 break;
2456
2457 default:
2458 *r = *q;
2459 break;
2460 } else
2461 *r = *q;
2462 }
2463 *r = '\0';
2464 ++q;
2465 } else {
2466 char *r;
2467
2468 /* In this case, the string is not quoted. We will break
2469 it using the coma (like for ints). If the user wants to
2470 include comas in a string, he just has to quote it */
2471
2472 /* Search the next coma */
2473 r = strchr(q, ',');
2474
2475 /* Found ? */
2476 if (r != (char *) NULL) {
2477 /* Recopy the current field */
2478 str = alloca(r - q + 1);
2479 memcpy(str, q, r - q);
2480
2481 /* I don't know if it is usefull, as the previous case
2482 doesn't null terminate the string ??? */
2483 str[r - q] = '\0';
2484
2485 /* Keep next fields */
2486 q = r;
2487 } else {
2488 /* last string */
2489 str = q;
2490 q = "";
2491 }
2492 }
2493
2494 if (*p == 's') {
2495 /* Normal string */
2496 obj_string_patch(f, sym->secidx, loc - contents, str);
2497 loc += tgt_sizeof_char_p;
2498 } else {
2499 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002500 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002501
2502 /* Get the size of each member */
2503 /* Probably we should do that outside the loop ? */
2504 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002505 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002506 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002507 return 0;
2508 }
2509 charssize = strtoul(p + 1, (char **) NULL, 10);
2510
2511 /* Check length */
2512 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002513 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002514 charssize - 1);
2515 return 0;
2516 }
2517
2518 /* Copy to location */
2519 strcpy((char *) loc, str);
2520 loc += charssize;
2521 }
2522 } else {
2523 long v = strtoul(q, &q, 0);
2524 switch (*p) {
2525 case 'b':
2526 *loc++ = v;
2527 break;
2528 case 'h':
2529 *(short *) loc = v;
2530 loc += tgt_sizeof_short;
2531 break;
2532 case 'i':
2533 *(int *) loc = v;
2534 loc += tgt_sizeof_int;
2535 break;
2536 case 'l':
2537 *(long *) loc = v;
2538 loc += tgt_sizeof_long;
2539 break;
2540
2541 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002542 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002543 return 0;
2544 }
2545 }
2546
2547 retry_end_of_value:
2548 switch (*q) {
2549 case '\0':
2550 goto end_of_arg;
2551
2552 case ' ':
2553 case '\t':
2554 case '\n':
2555 case '\r':
2556 ++q;
2557 goto retry_end_of_value;
2558
2559 case ',':
2560 if (++n > max) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002561 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002562 return 0;
2563 }
2564 ++q;
2565 break;
2566
2567 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002568 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002569 return 0;
2570 }
2571 }
2572
2573 end_of_arg:
2574 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002575 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002576 return 0;
2577 }
2578
2579 argc--, argv++;
2580 }
2581
2582 return 1;
2583}
2584
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002585#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002586static int new_is_module_checksummed(struct obj_file *f)
2587{
2588 const char *p = get_modinfo_value(f, "using_checksums");
2589 if (p)
2590 return atoi(p);
2591 else
2592 return 0;
2593}
2594
2595/* Get the module's kernel version in the canonical integer form. */
2596
2597static int
2598new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2599{
2600 char *p, *q;
2601 int a, b, c;
2602
2603 p = get_modinfo_value(f, "kernel_version");
2604 if (p == NULL)
2605 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002606 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002607
2608 a = strtoul(p, &p, 10);
2609 if (*p != '.')
2610 return -1;
2611 b = strtoul(p + 1, &p, 10);
2612 if (*p != '.')
2613 return -1;
2614 c = strtoul(p + 1, &q, 10);
2615 if (p + 1 == q)
2616 return -1;
2617
2618 return a << 16 | b << 8 | c;
2619}
2620
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002621#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002622
2623
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002624#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002625
2626/* Fetch the loaded modules, and all currently exported symbols. */
2627
2628static int new_get_kernel_symbols(void)
2629{
2630 char *module_names, *mn;
2631 struct external_module *modules, *m;
2632 struct new_module_symbol *syms, *s;
2633 size_t ret, bufsize, nmod, nsyms, i, j;
2634
2635 /* Collect the loaded modules. */
2636
2637 module_names = xmalloc(bufsize = 256);
2638 retry_modules_load:
2639 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002640 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002641 module_names = xrealloc(module_names, bufsize = ret);
2642 goto retry_modules_load;
2643 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002644 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002645 return 0;
2646 }
2647
2648 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002649
2650 /* Collect the modules' symbols. */
2651
Mark Whitley94fd4802001-03-12 23:08:34 +00002652 if (nmod){
2653 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2654 memset(modules, 0, nmod * sizeof(*modules));
2655 for (i = 0, mn = module_names, m = modules;
2656 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2657 struct new_module_info info;
2658
2659 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2660 if (errno == ENOENT) {
2661 /* The module was removed out from underneath us. */
2662 continue;
2663 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002664 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002665 return 0;
2666 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002667
2668 syms = xmalloc(bufsize = 1024);
2669 retry_mod_sym_load:
2670 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2671 switch (errno) {
2672 case ENOSPC:
2673 syms = xrealloc(syms, bufsize = ret);
2674 goto retry_mod_sym_load;
2675 case ENOENT:
2676 /* The module was removed out from underneath us. */
2677 continue;
2678 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00002679 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002680 return 0;
2681 }
2682 }
2683 nsyms = ret;
2684
2685 m->name = mn;
2686 m->addr = info.addr;
2687 m->nsyms = nsyms;
2688 m->syms = syms;
2689
2690 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2691 s->name += (unsigned long) syms;
2692 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 }
2694 }
2695
2696 /* Collect the kernel's symbols. */
2697
2698 syms = xmalloc(bufsize = 16 * 1024);
2699 retry_kern_sym_load:
2700 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002701 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002702 syms = xrealloc(syms, bufsize = ret);
2703 goto retry_kern_sym_load;
2704 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002705 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002706 return 0;
2707 }
2708 nksyms = nsyms = ret;
2709 ksyms = syms;
2710
2711 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2712 s->name += (unsigned long) syms;
2713 }
2714 return 1;
2715}
2716
2717
2718/* Return the kernel symbol checksum version, or zero if not used. */
2719
2720static int new_is_kernel_checksummed(void)
2721{
2722 struct new_module_symbol *s;
2723 size_t i;
2724
2725 /* Using_Versions is not the first symbol, but it should be in there. */
2726
2727 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2728 if (strcmp((char *) s->name, "Using_Versions") == 0)
2729 return s->value;
2730
2731 return 0;
2732}
2733
2734
2735static int new_create_this_module(struct obj_file *f, const char *m_name)
2736{
2737 struct obj_section *sec;
2738
2739 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2740 sizeof(struct new_module));
2741 memset(sec->contents, 0, sizeof(struct new_module));
2742
Miles Baderae28b042002-04-01 09:34:25 +00002743 obj_add_symbol(f, SPFX "__this_module", -1,
2744 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2745 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002746
2747 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2748 m_name);
2749
2750 return 1;
2751}
2752
Eric Andersen889dd202003-01-23 04:48:34 +00002753#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2754/* add an entry to the __ksymtab section, creating it if necessary */
2755static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2756{
2757 struct obj_section *sec;
2758 ElfW(Addr) ofs;
2759
2760 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2761 * If __ksymtab is defined but not marked alloc, x out the first character
2762 * (no obj_delete routine) and create a new __ksymtab with the correct
2763 * characteristics.
2764 */
2765 sec = obj_find_section(f, "__ksymtab");
2766 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2767 *((char *)(sec->name)) = 'x'; /* override const */
2768 sec = NULL;
2769 }
2770 if (!sec)
2771 sec = obj_create_alloced_section(f, "__ksymtab",
2772 tgt_sizeof_void_p, 0);
2773 if (!sec)
2774 return;
2775 sec->header.sh_flags |= SHF_ALLOC;
2776 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
2777 be byte-aligned */
2778 ofs = sec->header.sh_size;
2779 obj_symbol_patch(f, sec->idx, ofs, sym);
2780 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2781 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2782}
2783#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002784
2785static int new_create_module_ksymtab(struct obj_file *f)
2786{
2787 struct obj_section *sec;
2788 int i;
2789
2790 /* We must always add the module references. */
2791
2792 if (n_ext_modules_used) {
2793 struct new_module_ref *dep;
2794 struct obj_symbol *tm;
2795
2796 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2797 (sizeof(struct new_module_ref)
2798 * n_ext_modules_used));
2799 if (!sec)
2800 return 0;
2801
Miles Baderae28b042002-04-01 09:34:25 +00002802 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002803 dep = (struct new_module_ref *) sec->contents;
2804 for (i = 0; i < n_ext_modules; ++i)
2805 if (ext_modules[i].used) {
2806 dep->dep = ext_modules[i].addr;
2807 obj_symbol_patch(f, sec->idx,
2808 (char *) &dep->ref - sec->contents, tm);
2809 dep->next_ref = 0;
2810 ++dep;
2811 }
2812 }
2813
2814 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2815 size_t nsyms;
2816 int *loaded;
2817
2818 sec =
2819 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2820 0);
2821
2822 /* We don't want to export symbols residing in sections that
2823 aren't loaded. There are a number of these created so that
2824 we make sure certain module options don't appear twice. */
2825
2826 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2827 while (--i >= 0)
2828 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2829
2830 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2831 struct obj_symbol *sym;
2832 for (sym = f->symtab[i]; sym; sym = sym->next)
2833 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2834 && sym->secidx <= SHN_HIRESERVE
2835 && (sym->secidx >= SHN_LORESERVE
2836 || loaded[sym->secidx])) {
2837 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2838
2839 obj_symbol_patch(f, sec->idx, ofs, sym);
2840 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2841 sym->name);
2842
2843 nsyms++;
2844 }
2845 }
2846
2847 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2848 }
2849
2850 return 1;
2851}
2852
2853
2854static int
2855new_init_module(const char *m_name, struct obj_file *f,
2856 unsigned long m_size)
2857{
2858 struct new_module *module;
2859 struct obj_section *sec;
2860 void *image;
2861 int ret;
2862 tgt_long m_addr;
2863
2864 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002865 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002866 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002867 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002868 module = (struct new_module *) sec->contents;
2869 m_addr = sec->header.sh_addr;
2870
2871 module->size_of_struct = sizeof(*module);
2872 module->size = m_size;
2873 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2874
2875 sec = obj_find_section(f, "__ksymtab");
2876 if (sec && sec->header.sh_size) {
2877 module->syms = sec->header.sh_addr;
2878 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2879 }
2880
2881 if (n_ext_modules_used) {
2882 sec = obj_find_section(f, ".kmodtab");
2883 module->deps = sec->header.sh_addr;
2884 module->ndeps = n_ext_modules_used;
2885 }
2886
2887 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002888 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002889 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002890 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002891
2892 sec = obj_find_section(f, "__ex_table");
2893 if (sec) {
2894 module->ex_table_start = sec->header.sh_addr;
2895 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2896 }
2897
2898 sec = obj_find_section(f, ".text.init");
2899 if (sec) {
2900 module->runsize = sec->header.sh_addr - m_addr;
2901 }
2902 sec = obj_find_section(f, ".data.init");
2903 if (sec) {
2904 if (!module->runsize ||
2905 module->runsize > sec->header.sh_addr - m_addr)
2906 module->runsize = sec->header.sh_addr - m_addr;
2907 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002908 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2909 if (sec && sec->header.sh_size) {
2910 module->archdata_start = (void*)sec->header.sh_addr;
2911 module->archdata_end = module->archdata_start + sec->header.sh_size;
2912 }
2913 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2914 if (sec && sec->header.sh_size) {
2915 module->kallsyms_start = (void*)sec->header.sh_addr;
2916 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2917 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002918
2919 if (!arch_init_module(f, module))
2920 return 0;
2921
2922 /* Whew! All of the initialization is complete. Collect the final
2923 module image and give it to the kernel. */
2924
2925 image = xmalloc(m_size);
2926 obj_create_image(f, image);
2927
Eric Andersen64c8b172001-04-05 07:33:10 +00002928 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002929 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002930 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002931
2932 free(image);
2933
2934 return ret == 0;
2935}
2936
2937#else
2938
2939#define new_init_module(x, y, z) TRUE
2940#define new_create_this_module(x, y) 0
Eric Andersen889dd202003-01-23 04:48:34 +00002941#define new_add_ksymtab(x, y) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002942#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002943#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002944
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002945#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002946
2947
2948/*======================================================================*/
2949
Eric Andersen044228d2001-07-17 01:12:36 +00002950static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002951obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2952 const char *string)
2953{
2954 struct obj_string_patch *p;
2955 struct obj_section *strsec;
2956 size_t len = strlen(string) + 1;
2957 char *loc;
2958
2959 p = xmalloc(sizeof(*p));
2960 p->next = f->string_patches;
2961 p->reloc_secidx = secidx;
2962 p->reloc_offset = offset;
2963 f->string_patches = p;
2964
2965 strsec = obj_find_section(f, ".kstrtab");
2966 if (strsec == NULL) {
2967 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2968 p->string_offset = 0;
2969 loc = strsec->contents;
2970 } else {
2971 p->string_offset = strsec->header.sh_size;
2972 loc = obj_extend_section(strsec, len);
2973 }
2974 memcpy(loc, string, len);
2975
2976 return 1;
2977}
2978
Eric Andersen6d139642001-12-29 04:15:13 +00002979#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00002980static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002981obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2982 struct obj_symbol *sym)
2983{
2984 struct obj_symbol_patch *p;
2985
2986 p = xmalloc(sizeof(*p));
2987 p->next = f->symbol_patches;
2988 p->reloc_secidx = secidx;
2989 p->reloc_offset = offset;
2990 p->sym = sym;
2991 f->symbol_patches = p;
2992
2993 return 1;
2994}
Eric Andersen6d139642001-12-29 04:15:13 +00002995#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002996
Eric Andersen044228d2001-07-17 01:12:36 +00002997static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002998{
2999 unsigned long i;
3000 int ret = 1;
3001
3002 for (i = 0; i < HASH_BUCKETS; ++i) {
3003 struct obj_symbol *sym;
3004 for (sym = f->symtab[i]; sym; sym = sym->next)
3005 if (sym->secidx == SHN_UNDEF) {
3006 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
3007 sym->secidx = SHN_ABS;
3008 sym->value = 0;
3009 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003010 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003011 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003012 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003013 ret = 0;
3014 }
3015 }
3016 }
3017
3018 return ret;
3019}
3020
Eric Andersen044228d2001-07-17 01:12:36 +00003021static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003022{
3023 struct common_entry {
3024 struct common_entry *next;
3025 struct obj_symbol *sym;
3026 } *common_head = NULL;
3027
3028 unsigned long i;
3029
3030 for (i = 0; i < HASH_BUCKETS; ++i) {
3031 struct obj_symbol *sym;
3032 for (sym = f->symtab[i]; sym; sym = sym->next)
3033 if (sym->secidx == SHN_COMMON) {
3034 /* Collect all COMMON symbols and sort them by size so as to
3035 minimize space wasted by alignment requirements. */
3036 {
3037 struct common_entry **p, *n;
3038 for (p = &common_head; *p; p = &(*p)->next)
3039 if (sym->size <= (*p)->sym->size)
3040 break;
3041
3042 n = alloca(sizeof(*n));
3043 n->next = *p;
3044 n->sym = sym;
3045 *p = n;
3046 }
3047 }
3048 }
3049
3050 for (i = 1; i < f->local_symtab_size; ++i) {
3051 struct obj_symbol *sym = f->local_symtab[i];
3052 if (sym && sym->secidx == SHN_COMMON) {
3053 struct common_entry **p, *n;
3054 for (p = &common_head; *p; p = &(*p)->next)
3055 if (sym == (*p)->sym)
3056 break;
3057 else if (sym->size < (*p)->sym->size) {
3058 n = alloca(sizeof(*n));
3059 n->next = *p;
3060 n->sym = sym;
3061 *p = n;
3062 break;
3063 }
3064 }
3065 }
3066
3067 if (common_head) {
3068 /* Find the bss section. */
3069 for (i = 0; i < f->header.e_shnum; ++i)
3070 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3071 break;
3072
3073 /* If for some reason there hadn't been one, create one. */
3074 if (i == f->header.e_shnum) {
3075 struct obj_section *sec;
3076
3077 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3078 f->sections[i] = sec = arch_new_section();
3079 f->header.e_shnum = i + 1;
3080
3081 memset(sec, 0, sizeof(*sec));
3082 sec->header.sh_type = SHT_PROGBITS;
3083 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3084 sec->name = ".bss";
3085 sec->idx = i;
3086 }
3087
3088 /* Allocate the COMMONS. */
3089 {
3090 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3091 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3092 struct common_entry *c;
3093
3094 for (c = common_head; c; c = c->next) {
3095 ElfW(Addr) align = c->sym->value;
3096
3097 if (align > max_align)
3098 max_align = align;
3099 if (bss_size & (align - 1))
3100 bss_size = (bss_size | (align - 1)) + 1;
3101
3102 c->sym->secidx = i;
3103 c->sym->value = bss_size;
3104
3105 bss_size += c->sym->size;
3106 }
3107
3108 f->sections[i]->header.sh_size = bss_size;
3109 f->sections[i]->header.sh_addralign = max_align;
3110 }
3111 }
3112
3113 /* For the sake of patch relocation and parameter initialization,
3114 allocate zeroed data for NOBITS sections now. Note that after
3115 this we cannot assume NOBITS are really empty. */
3116 for (i = 0; i < f->header.e_shnum; ++i) {
3117 struct obj_section *s = f->sections[i];
3118 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003119 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003120 s->contents = memset(xmalloc(s->header.sh_size),
3121 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003122 else
3123 s->contents = NULL;
3124
Eric Andersen9f16d612000-06-12 23:11:16 +00003125 s->header.sh_type = SHT_PROGBITS;
3126 }
3127 }
3128}
3129
Eric Andersen044228d2001-07-17 01:12:36 +00003130static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003131{
3132 unsigned long dot = 0;
3133 struct obj_section *sec;
3134
3135 /* Finalize the positions of the sections relative to one another. */
3136
3137 for (sec = f->load_order; sec; sec = sec->load_next) {
3138 ElfW(Addr) align;
3139
3140 align = sec->header.sh_addralign;
3141 if (align && (dot & (align - 1)))
3142 dot = (dot | (align - 1)) + 1;
3143
3144 sec->header.sh_addr = dot;
3145 dot += sec->header.sh_size;
3146 }
3147
3148 return dot;
3149}
3150
Eric Andersen044228d2001-07-17 01:12:36 +00003151static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003152{
3153 int i, n = f->header.e_shnum;
3154 int ret = 1;
3155
3156 /* Finalize the addresses of the sections. */
3157
3158 f->baseaddr = base;
3159 for (i = 0; i < n; ++i)
3160 f->sections[i]->header.sh_addr += base;
3161
3162 /* And iterate over all of the relocations. */
3163
3164 for (i = 0; i < n; ++i) {
3165 struct obj_section *relsec, *symsec, *targsec, *strsec;
3166 ElfW(RelM) * rel, *relend;
3167 ElfW(Sym) * symtab;
3168 const char *strtab;
3169
3170 relsec = f->sections[i];
3171 if (relsec->header.sh_type != SHT_RELM)
3172 continue;
3173
3174 symsec = f->sections[relsec->header.sh_link];
3175 targsec = f->sections[relsec->header.sh_info];
3176 strsec = f->sections[symsec->header.sh_link];
3177
3178 rel = (ElfW(RelM) *) relsec->contents;
3179 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3180 symtab = (ElfW(Sym) *) symsec->contents;
3181 strtab = (const char *) strsec->contents;
3182
3183 for (; rel < relend; ++rel) {
3184 ElfW(Addr) value = 0;
3185 struct obj_symbol *intsym = NULL;
3186 unsigned long symndx;
3187 ElfW(Sym) * extsym = 0;
3188 const char *errmsg;
3189
3190 /* Attempt to find a value to use for this relocation. */
3191
3192 symndx = ELFW(R_SYM) (rel->r_info);
3193 if (symndx) {
3194 /* Note we've already checked for undefined symbols. */
3195
3196 extsym = &symtab[symndx];
3197 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3198 /* Local symbols we look up in the local table to be sure
3199 we get the one that is really intended. */
3200 intsym = f->local_symtab[symndx];
3201 } else {
3202 /* Others we look up in the hash table. */
3203 const char *name;
3204 if (extsym->st_name)
3205 name = strtab + extsym->st_name;
3206 else
3207 name = f->sections[extsym->st_shndx]->name;
3208 intsym = obj_find_symbol(f, name);
3209 }
3210
3211 value = obj_symbol_final_value(f, intsym);
3212 intsym->referenced = 1;
3213 }
3214#if SHT_RELM == SHT_RELA
3215#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3216 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3217 if (!extsym || !extsym->st_name ||
3218 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
3219#endif
3220 value += rel->r_addend;
3221#endif
3222
3223 /* Do it! */
3224 switch (arch_apply_relocation
3225 (f, targsec, symsec, intsym, rel, value)) {
3226 case obj_reloc_ok:
3227 break;
3228
3229 case obj_reloc_overflow:
3230 errmsg = "Relocation overflow";
3231 goto bad_reloc;
3232 case obj_reloc_dangerous:
3233 errmsg = "Dangerous relocation";
3234 goto bad_reloc;
3235 case obj_reloc_unhandled:
3236 errmsg = "Unhandled relocation";
3237 bad_reloc:
3238 if (extsym) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003239 bb_error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003240 (long) ELFW(R_TYPE) (rel->r_info),
3241 strtab + extsym->st_name);
3242 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003243 bb_error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003244 (long) ELFW(R_TYPE) (rel->r_info));
3245 }
3246 ret = 0;
3247 break;
3248 }
3249 }
3250 }
3251
3252 /* Finally, take care of the patches. */
3253
3254 if (f->string_patches) {
3255 struct obj_string_patch *p;
3256 struct obj_section *strsec;
3257 ElfW(Addr) strsec_base;
3258 strsec = obj_find_section(f, ".kstrtab");
3259 strsec_base = strsec->header.sh_addr;
3260
3261 for (p = f->string_patches; p; p = p->next) {
3262 struct obj_section *targsec = f->sections[p->reloc_secidx];
3263 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3264 = strsec_base + p->string_offset;
3265 }
3266 }
3267
3268 if (f->symbol_patches) {
3269 struct obj_symbol_patch *p;
3270
3271 for (p = f->symbol_patches; p; p = p->next) {
3272 struct obj_section *targsec = f->sections[p->reloc_secidx];
3273 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3274 = obj_symbol_final_value(f, p->sym);
3275 }
3276 }
3277
3278 return ret;
3279}
3280
Eric Andersen044228d2001-07-17 01:12:36 +00003281static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003282{
3283 struct obj_section *sec;
3284 ElfW(Addr) base = f->baseaddr;
3285
3286 for (sec = f->load_order; sec; sec = sec->load_next) {
3287 char *secimg;
3288
Eric Andersen2bf658d2001-02-24 20:01:53 +00003289 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003290 continue;
3291
3292 secimg = image + (sec->header.sh_addr - base);
3293
3294 /* Note that we allocated data for NOBITS sections earlier. */
3295 memcpy(secimg, sec->contents, sec->header.sh_size);
3296 }
3297
3298 return 1;
3299}
3300
3301/*======================================================================*/
3302
Eric Andersen044228d2001-07-17 01:12:36 +00003303static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003304{
3305 struct obj_file *f;
3306 ElfW(Shdr) * section_headers;
3307 int shnum, i;
3308 char *shstrtab;
3309
3310 /* Read the file header. */
3311
3312 f = arch_new_file();
3313 memset(f, 0, sizeof(*f));
3314 f->symbol_cmp = strcmp;
3315 f->symbol_hash = obj_elf_hash;
3316 f->load_order_search_start = &f->load_order;
3317
3318 fseek(fp, 0, SEEK_SET);
3319 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003320 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003321 return NULL;
3322 }
3323
3324 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3325 || f->header.e_ident[EI_MAG1] != ELFMAG1
3326 || f->header.e_ident[EI_MAG2] != ELFMAG2
3327 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003328 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003329 return NULL;
3330 }
3331 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3332 || f->header.e_ident[EI_DATA] != ELFDATAM
3333 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3334 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003335 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003336 return NULL;
3337 }
3338 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003339 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003340 return NULL;
3341 }
3342
3343 /* Read the section headers. */
3344
3345 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003346 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003347 (unsigned long) f->header.e_shentsize,
3348 (unsigned long) sizeof(ElfW(Shdr)));
3349 return NULL;
3350 }
3351
3352 shnum = f->header.e_shnum;
3353 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3354 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3355
3356 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3357 fseek(fp, f->header.e_shoff, SEEK_SET);
3358 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003359 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003360 return NULL;
3361 }
3362
3363 /* Read the section data. */
3364
3365 for (i = 0; i < shnum; ++i) {
3366 struct obj_section *sec;
3367
3368 f->sections[i] = sec = arch_new_section();
3369 memset(sec, 0, sizeof(*sec));
3370
3371 sec->header = section_headers[i];
3372 sec->idx = i;
3373
Eric Andersen2bf658d2001-02-24 20:01:53 +00003374 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003375 case SHT_NULL:
3376 case SHT_NOTE:
3377 case SHT_NOBITS:
3378 /* ignore */
3379 break;
3380
3381 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003382#if LOADBITS
3383 if (!loadprogbits) {
3384 sec->contents = NULL;
3385 break;
3386 }
3387#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 case SHT_SYMTAB:
3389 case SHT_STRTAB:
3390 case SHT_RELM:
3391 if (sec->header.sh_size > 0) {
3392 sec->contents = xmalloc(sec->header.sh_size);
3393 fseek(fp, sec->header.sh_offset, SEEK_SET);
3394 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003395 bb_perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 return NULL;
3397 }
3398 } else {
3399 sec->contents = NULL;
3400 }
3401 break;
3402
3403#if SHT_RELM == SHT_REL
3404 case SHT_RELA:
Manuel Novoa III cad53642003-03-19 09:13:01 +00003405 bb_error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003406 return NULL;
3407#else
3408 case SHT_REL:
Manuel Novoa III cad53642003-03-19 09:13:01 +00003409 bb_error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003410 return NULL;
3411#endif
3412
3413 default:
3414 if (sec->header.sh_type >= SHT_LOPROC) {
3415 /* Assume processor specific section types are debug
3416 info and can safely be ignored. If this is ever not
3417 the case (Hello MIPS?), don't put ifdefs here but
3418 create an arch_load_proc_section(). */
3419 break;
3420 }
3421
Manuel Novoa III cad53642003-03-19 09:13:01 +00003422 bb_error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003423 (long) sec->header.sh_type);
3424 return NULL;
3425 }
3426 }
3427
3428 /* Do what sort of interpretation as needed by each section. */
3429
3430 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3431
3432 for (i = 0; i < shnum; ++i) {
3433 struct obj_section *sec = f->sections[i];
3434 sec->name = shstrtab + sec->header.sh_name;
3435 }
3436
3437 for (i = 0; i < shnum; ++i) {
3438 struct obj_section *sec = f->sections[i];
3439
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003440 /* .modinfo should be contents only but gcc has no attribute for that.
3441 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3442 */
3443 if (strcmp(sec->name, ".modinfo") == 0)
3444 sec->header.sh_flags &= ~SHF_ALLOC;
3445
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 if (sec->header.sh_flags & SHF_ALLOC)
3447 obj_insert_section_load_order(f, sec);
3448
3449 switch (sec->header.sh_type) {
3450 case SHT_SYMTAB:
3451 {
3452 unsigned long nsym, j;
3453 char *strtab;
3454 ElfW(Sym) * sym;
3455
3456 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003457 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003458 (unsigned long) sec->header.sh_entsize,
3459 (unsigned long) sizeof(ElfW(Sym)));
3460 return NULL;
3461 }
3462
3463 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3464 strtab = f->sections[sec->header.sh_link]->contents;
3465 sym = (ElfW(Sym) *) sec->contents;
3466
3467 /* Allocate space for a table of local symbols. */
3468 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003469 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003470
3471 /* Insert all symbols into the hash table. */
3472 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3473 const char *name;
3474 if (sym->st_name)
3475 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003476 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003477 name = f->sections[sym->st_shndx]->name;
3478
3479 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3480 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003481 }
3482 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003483 break;
3484
3485 case SHT_RELM:
3486 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003487 bb_error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003488 (unsigned long) sec->header.sh_entsize,
3489 (unsigned long) sizeof(ElfW(RelM)));
3490 return NULL;
3491 }
3492 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003493 /* XXX Relocation code from modutils-2.3.19 is not here.
3494 * Why? That's about 20 lines of code from obj/obj_load.c,
3495 * which gets done in a second pass through the sections.
3496 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003497 }
3498 }
3499
3500 return f;
3501}
3502
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003503#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003504/*
3505 * load the unloaded sections directly into the memory allocated by
3506 * kernel for the module
3507 */
3508
Eric Andersenac5dbd12001-08-22 05:26:08 +00003509static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003510{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003511 ElfW(Addr) base = f->baseaddr;
3512 struct obj_section* sec;
3513
3514 for (sec = f->load_order; sec; sec = sec->load_next) {
3515
3516 /* section already loaded? */
3517 if (sec->contents != NULL)
3518 continue;
3519
3520 if (sec->header.sh_size == 0)
3521 continue;
3522
3523 sec->contents = imagebase + (sec->header.sh_addr - base);
3524 fseek(fp, sec->header.sh_offset, SEEK_SET);
3525 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003526 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003527 return 0;
3528 }
3529
3530 }
3531 return 1;
3532}
3533#endif
3534
Eric Andersen9f16d612000-06-12 23:11:16 +00003535static void hide_special_symbols(struct obj_file *f)
3536{
3537 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003538 SPFX "cleanup_module",
3539 SPFX "init_module",
3540 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003541 NULL
3542 };
3543
3544 struct obj_symbol *sym;
3545 const char *const *p;
3546
3547 for (p = specials; *p; ++p)
3548 if ((sym = obj_find_symbol(f, *p)) != NULL)
3549 sym->info =
3550 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3551}
3552
Eric Andersen71ae64b2002-10-10 04:20:21 +00003553#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003554static int obj_gpl_license(struct obj_file *f, const char **license)
3555{
3556 struct obj_section *sec;
3557 /* This list must match *exactly* the list of allowable licenses in
3558 * linux/include/linux/module.h. Checking for leading "GPL" will not
3559 * work, somebody will use "GPL sucks, this is proprietary".
3560 */
3561 static const char *gpl_licenses[] = {
3562 "GPL",
3563 "GPL v2",
3564 "GPL and additional rights",
3565 "Dual BSD/GPL",
3566 "Dual MPL/GPL",
3567 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003568
Eric Andersen166fa462002-09-16 05:30:24 +00003569 if ((sec = obj_find_section(f, ".modinfo"))) {
3570 const char *value, *ptr, *endptr;
3571 ptr = sec->contents;
3572 endptr = ptr + sec->header.sh_size;
3573 while (ptr < endptr) {
3574 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3575 int i;
3576 if (license)
3577 *license = value+1;
3578 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3579 if (strcmp(value+1, gpl_licenses[i]) == 0)
3580 return(0);
3581 }
3582 return(2);
3583 }
3584 if (strchr(ptr, '\0'))
3585 ptr = strchr(ptr, '\0') + 1;
3586 else
3587 ptr = endptr;
3588 }
3589 }
3590 return(1);
3591}
3592
3593#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3594#define TAINT_PROPRIETORY_MODULE (1<<0)
3595#define TAINT_FORCED_MODULE (1<<1)
3596#define TAINT_UNSAFE_SMP (1<<2)
3597#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3598
3599static void set_tainted(struct obj_file *f, int fd, char *m_name,
3600 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3601{
3602 char buf[80];
3603 int oldval;
3604 static int first = 1;
3605 if (fd < 0 && !kernel_has_tainted)
3606 return; /* New modutils on old kernel */
3607 printf("Warning: loading %s will taint the kernel: %s%s\n",
3608 m_name, text1, text2);
3609 if (first) {
3610 printf(" See %s for information about tainted modules\n", TAINT_URL);
3611 first = 0;
3612 }
3613 if (fd >= 0) {
3614 read(fd, buf, sizeof(buf)-1);
3615 buf[sizeof(buf)-1] = '\0';
3616 oldval = strtoul(buf, NULL, 10);
3617 sprintf(buf, "%d\n", oldval | taint);
3618 write(fd, buf, strlen(buf));
3619 }
3620}
3621
3622/* Check if loading this module will taint the kernel. */
3623static void check_tainted_module(struct obj_file *f, char *m_name)
3624{
3625 static const char tainted_file[] = TAINT_FILENAME;
3626 int fd, kernel_has_tainted;
3627 const char *ptr;
3628
3629 kernel_has_tainted = 1;
3630 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3631 if (errno == ENOENT)
3632 kernel_has_tainted = 0;
3633 else if (errno == EACCES)
3634 kernel_has_tainted = 1;
3635 else {
3636 perror(tainted_file);
3637 kernel_has_tainted = 0;
3638 }
3639 }
3640
3641 switch (obj_gpl_license(f, &ptr)) {
3642 case 0:
3643 break;
3644 case 1:
3645 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3646 break;
3647 case 2:
3648 /* The module has a non-GPL license so we pretend that the
3649 * kernel always has a taint flag to get a warning even on
3650 * kernels without the proc flag.
3651 */
3652 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3653 break;
3654 default:
3655 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3656 break;
3657 }
3658
3659 if (flag_force_load)
3660 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3661
3662 if (fd >= 0)
3663 close(fd);
3664}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003665#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3666#define check_tainted_module(x, y) do { } while(0);
3667#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003668
Eric Andersen889dd202003-01-23 04:48:34 +00003669#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3670/* add module source, timestamp, kernel version and a symbol for the
3671 * start of some sections. this info is used by ksymoops to do better
3672 * debugging.
3673 */
3674static int
3675get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3676{
3677#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
3678 if (get_modinfo_value(f, "kernel_version") == NULL)
3679 return old_get_module_version(f, str);
3680 else
3681 return new_get_module_version(f, str);
3682#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3683 strncpy(str, "???", sizeof(str));
3684 return -1;
3685#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3686}
3687
3688/* add module source, timestamp, kernel version and a symbol for the
3689 * start of some sections. this info is used by ksymoops to do better
3690 * debugging.
3691 */
3692static void
3693add_ksymoops_symbols(struct obj_file *f, const char *filename,
3694 const char *m_name)
3695{
3696 static const char symprefix[] = "__insmod_";
3697 struct obj_section *sec;
3698 struct obj_symbol *sym;
3699 char *name, *absolute_filename;
3700 char str[STRVERSIONLEN], real[PATH_MAX];
3701 int i, l, lm_name, lfilename, use_ksymtab, version;
3702 struct stat statbuf;
3703
3704 static const char *section_names[] = {
3705 ".text",
3706 ".rodata",
3707 ".data",
3708 ".bss"
3709 ".sbss"
3710 };
3711
3712 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003713 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003714 }
3715 else {
3716 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003717 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003718 errno = save_errno;
3719 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003720 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003721 }
3722
3723 lm_name = strlen(m_name);
3724 lfilename = strlen(absolute_filename);
3725
3726 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3727 * are not to be exported. otherwise leave ksymtab alone for now, the
3728 * "export all symbols" compatibility code will export these symbols later.
3729 */
3730 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3731
3732 if ((sec = obj_find_section(f, ".this"))) {
3733 /* tag the module header with the object name, last modified
3734 * timestamp and module version. worst case for module version
3735 * is 0xffffff, decimal 16777215. putting all three fields in
3736 * one symbol is less readable but saves kernel space.
3737 */
3738 l = sizeof(symprefix)+ /* "__insmod_" */
3739 lm_name+ /* module name */
3740 2+ /* "_O" */
3741 lfilename+ /* object filename */
3742 2+ /* "_M" */
3743 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3744 2+ /* "_V" */
3745 8+ /* version in dec */
3746 1; /* nul */
3747 name = xmalloc(l);
3748 if (stat(absolute_filename, &statbuf) != 0)
3749 statbuf.st_mtime = 0;
3750 version = get_module_version(f, str); /* -1 if not found */
3751 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
3752 symprefix, m_name, absolute_filename,
3753 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3754 version);
3755 sym = obj_add_symbol(f, name, -1,
3756 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3757 sec->idx, sec->header.sh_addr, 0);
3758 if (use_ksymtab)
3759 new_add_ksymtab(f, sym);
3760 }
3761 free(absolute_filename);
3762#ifdef _NOT_SUPPORTED_
3763 /* record where the persistent data is going, same address as previous symbol */
3764
3765 if (f->persist) {
3766 l = sizeof(symprefix)+ /* "__insmod_" */
3767 lm_name+ /* module name */
3768 2+ /* "_P" */
3769 strlen(f->persist)+ /* data store */
3770 1; /* nul */
3771 name = xmalloc(l);
3772 snprintf(name, l, "%s%s_P%s",
3773 symprefix, m_name, f->persist);
3774 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3775 sec->idx, sec->header.sh_addr, 0);
3776 if (use_ksymtab)
3777 new_add_ksymtab(f, sym);
3778 }
3779#endif /* _NOT_SUPPORTED_ */
3780 /* tag the desired sections if size is non-zero */
3781
3782 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3783 if ((sec = obj_find_section(f, section_names[i])) &&
3784 sec->header.sh_size) {
3785 l = sizeof(symprefix)+ /* "__insmod_" */
3786 lm_name+ /* module name */
3787 2+ /* "_S" */
3788 strlen(sec->name)+ /* section name */
3789 2+ /* "_L" */
3790 8+ /* length in dec */
3791 1; /* nul */
3792 name = xmalloc(l);
3793 snprintf(name, l, "%s%s_S%s_L%ld",
3794 symprefix, m_name, sec->name,
3795 (long)sec->header.sh_size);
3796 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3797 sec->idx, sec->header.sh_addr, 0);
3798 if (use_ksymtab)
3799 new_add_ksymtab(f, sym);
3800 }
3801 }
3802}
3803#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3804
Eric Andersenbe65c352003-01-23 04:57:35 +00003805#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3806static void print_load_map(struct obj_file *f)
3807{
3808 struct obj_symbol *sym;
3809 struct obj_symbol **all, **p;
3810 struct obj_section *sec;
3811 int i, nsyms, *loaded;
3812
3813 /* Report on the section layout. */
3814
3815 printf("Sections: Size %-*s Align\n",
3816 (int) (2 * sizeof(void *)), "Address");
3817
3818 for (sec = f->load_order; sec; sec = sec->load_next) {
3819 int a;
3820 unsigned long tmp;
3821
3822 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3823 tmp >>= 1;
3824 if (a == -1)
3825 a = 0;
3826
3827 printf("%-15s %08lx %0*lx 2**%d\n",
3828 sec->name,
3829 (long)sec->header.sh_size,
3830 (int) (2 * sizeof(void *)),
3831 (long)sec->header.sh_addr,
3832 a);
3833 }
3834#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3835 /* Quick reference which section indicies are loaded. */
3836
3837 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3838 while (--i >= 0)
3839 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3840
3841 /* Collect the symbols we'll be listing. */
3842
3843 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3844 for (sym = f->symtab[i]; sym; sym = sym->next)
3845 if (sym->secidx <= SHN_HIRESERVE
3846 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3847 ++nsyms;
3848
3849 all = alloca(nsyms * sizeof(struct obj_symbol *));
3850
3851 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3852 for (sym = f->symtab[i]; sym; sym = sym->next)
3853 if (sym->secidx <= SHN_HIRESERVE
3854 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3855 *p++ = sym;
3856
3857 /* And list them. */
3858 printf("\nSymbols:\n");
3859 for (p = all; p < all + nsyms; ++p) {
3860 char type = '?';
3861 unsigned long value;
3862
3863 sym = *p;
3864 if (sym->secidx == SHN_ABS) {
3865 type = 'A';
3866 value = sym->value;
3867 } else if (sym->secidx == SHN_UNDEF) {
3868 type = 'U';
3869 value = 0;
3870 } else {
3871 sec = f->sections[sym->secidx];
3872
3873 if (sec->header.sh_type == SHT_NOBITS)
3874 type = 'B';
3875 else if (sec->header.sh_flags & SHF_ALLOC) {
3876 if (sec->header.sh_flags & SHF_EXECINSTR)
3877 type = 'T';
3878 else if (sec->header.sh_flags & SHF_WRITE)
3879 type = 'D';
3880 else
3881 type = 'R';
3882 }
3883 value = sym->value + sec->header.sh_addr;
3884 }
3885
3886 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
3887 type = tolower(type);
3888
3889 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3890 type, sym->name);
3891 }
3892#endif
3893}
3894
3895#endif
3896
Eric Andersen9f16d612000-06-12 23:11:16 +00003897extern int insmod_main( int argc, char **argv)
3898{
Eric Andersena18aaf12001-01-24 19:07:09 +00003899 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003900 int k_crcs;
3901 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003902 int len;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003903 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003904 unsigned long m_size;
3905 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003906 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003907 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003908 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003909 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003910 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003911#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003912 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003913 char m_strversion[STRVERSIONLEN];
3914 int m_version;
3915 int m_crcs;
3916#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003917#ifdef CONFIG_FEATURE_CLEAN_UP
3918 FILE *fp = 0;
3919#else
3920 FILE *fp;
3921#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003922#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3923 int flag_print_load_map = 0;
3924#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003925
Erik Andersene49d5ec2000-02-08 19:58:47 +00003926 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003927#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3928 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0) {
3929#else
Eric Andersenb493dec2002-07-02 19:14:23 +00003930 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
Eric Andersenbe65c352003-01-23 04:57:35 +00003931#endif
Eric Andersena18aaf12001-01-24 19:07:09 +00003932 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003933 case 'f': /* force loading */
3934 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003935 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003936 case 'k': /* module loaded by kerneld, auto-cleanable */
3937 flag_autoclean = 1;
3938 break;
Eric Andersenc088c582002-05-03 10:34:35 +00003939 case 's': /* log to syslog */
3940 /* log to syslog -- not supported */
3941 /* but kernel needs this for request_module(), */
3942 /* as this calls: modprobe -k -s -- <module> */
3943 /* so silently ignore this flag */
3944 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003945 case 'v': /* verbose output */
3946 flag_verbose = 1;
3947 break;
Eric Andersenb493dec2002-07-02 19:14:23 +00003948 case 'q': /* silent */
3949 flag_quiet = 1;
3950 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003951 case 'x': /* do not export externs */
3952 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003953 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003954 case 'o': /* name the output module */
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00003955 free(m_name);
Manuel Novoa III cad53642003-03-19 09:13:01 +00003956 m_name = bb_xstrdup(optarg);
Eric Andersen155c89b2001-01-25 04:11:06 +00003957 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003958 case 'L': /* Stub warning */
3959 /* This is needed for compatibility with modprobe.
3960 * In theory, this does locking, but we don't do
3961 * that. So be careful and plan your life around not
3962 * loading the same module 50 times concurrently. */
3963 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003964#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3965 case 'm': /* print module load map */
3966 flag_print_load_map = 1;
3967 break;
3968#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +00003969 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00003970 bb_show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003971 }
Erik Andersend387d011999-12-21 02:55:11 +00003972 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003973
3974 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003975 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003976 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003977
Erik Andersene49d5ec2000-02-08 19:58:47 +00003978 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003979 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003980 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003981 len = strlen(tmp);
3982
Eric Andersen6fb4e482002-06-06 14:24:57 +00003983 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3984 len-=2;
3985 tmp[len] = '\0';
Eric Andersen155c89b2001-01-25 04:11:06 +00003986 }
Eric Andersen2d342152002-06-18 05:16:25 +00003987
Manuel Novoa III cad53642003-03-19 09:13:01 +00003988 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003989
Eric Andersen61f83052002-06-22 17:15:42 +00003990 if (!m_name) {
3991 m_name = tmp;
3992 } else {
3993 free(tmp1);
3994 tmp1 = 0; /* flag for free(m_name) before exit() */
3995 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003996
Eric Andersen14d35432001-05-14 17:07:32 +00003997 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003998 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3999 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004000 struct utsname myuname;
4001
4002 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4003 * but do not error out yet if we fail to find it... */
4004 if (uname(&myuname) == 0) {
Robert Griebld378c312002-07-19 00:05:54 +00004005 char *module_dir;
4006 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004007 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004008
4009 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004010 /* Jump through hoops in case /lib/modules/`uname -r`
4011 * is a symlink. We do not want recursive_action to
4012 * follow symlinks, but we do want to follow the
4013 * /lib/modules/`uname -r` dir, So resolve it ourselves
4014 * if it is a link... */
Robert Griebld378c312002-07-19 00:05:54 +00004015 if (realpath (tmdn, real_module_dir) == NULL)
4016 module_dir = tmdn;
4017 else
4018 module_dir = real_module_dir;
4019 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00004020 check_module_name_match, 0, m_fullName);
Robert Griebld378c312002-07-19 00:05:54 +00004021 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004022 }
4023
4024 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004025 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004026 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004027 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004028
4029 free(m_filename);
4030 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004031 if (realpath (_PATH_MODULES, module_dir) == NULL)
4032 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004033 /* No module found under /lib/modules/`uname -r`, this
4034 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004035 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
4036 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004037 {
Eric Andersen61f83052002-06-22 17:15:42 +00004038 if (m_filename == 0
Eric Andersen14d35432001-05-14 17:07:32 +00004039 || ((fp = fopen(m_filename, "r")) == NULL))
4040 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004041 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004042 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004043 }
4044 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004045 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004046 }
4047 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004048 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004049
Eric Andersen14d35432001-05-14 17:07:32 +00004050 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004051
Eric Andersen8ae319a2001-05-21 16:09:18 +00004052 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004053 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004054
Eric Andersen9f16d612000-06-12 23:11:16 +00004055 if (get_modinfo_value(f, "kernel_version") == NULL)
4056 m_has_modinfo = 0;
4057 else
4058 m_has_modinfo = 1;
4059
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004060#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004061 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004062 if (!flag_quiet) {
4063 if (uname(&uts_info) < 0)
4064 uts_info.release[0] = '\0';
4065 if (m_has_modinfo) {
4066 m_version = new_get_module_version(f, m_strversion);
Eric Andersen9f16d612000-06-12 23:11:16 +00004067 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00004068 m_version = old_get_module_version(f, m_strversion);
4069 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004070 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004071 "compiled for");
4072 goto out;
4073 }
4074 }
4075
4076 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4077 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004078 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004079 "\t%s was compiled for kernel version %s\n"
4080 "\twhile this kernel is version %s",
4081 m_filename, m_strversion, uts_info.release);
4082 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004083 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004084 "\t%s was compiled for kernel version %s\n"
4085 "\twhile this kernel is version %s.",
4086 m_filename, m_strversion, uts_info.release);
4087 goto out;
4088 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004089 }
4090 }
4091 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004092#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004093
4094 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
4095
4096 if (k_new_syscalls) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004097#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00004098 if (!new_get_kernel_symbols())
4099 goto out;
4100 k_crcs = new_is_kernel_checksummed();
4101#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004102 bb_error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004103 goto out;
4104#endif
4105 } else {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004106#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00004107 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004108 goto out;
4109 k_crcs = old_is_kernel_checksummed();
4110#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004111 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004112 goto out;
4113#endif
4114 }
4115
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004116#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004117 if (m_has_modinfo)
4118 m_crcs = new_is_module_checksummed(f);
4119 else
4120 m_crcs = old_is_module_checksummed(f);
4121
4122 if (m_crcs != k_crcs)
4123 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004124#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004125
Erik Andersene49d5ec2000-02-08 19:58:47 +00004126 /* Let the module know about the kernel symbols. */
4127 add_kernel_symbols(f);
4128
Eric Andersen9f16d612000-06-12 23:11:16 +00004129 /* Allocate common symbols, symbol tables, and string tables. */
4130
4131 if (k_new_syscalls
4132 ? !new_create_this_module(f, m_name)
4133 : !old_create_mod_use_count(f))
4134 {
4135 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004136 }
4137
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 if (!obj_check_undefineds(f)) {
4139 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004140 }
4141 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004142 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004143
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004144 /* done with the module name, on to the optional var=value arguments */
4145 ++optind;
4146
Eric Andersen9f16d612000-06-12 23:11:16 +00004147 if (optind < argc) {
4148 if (m_has_modinfo
4149 ? !new_process_module_arguments(f, argc - optind, argv + optind)
4150 : !old_process_module_arguments(f, argc - optind, argv + optind))
4151 {
4152 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004153 }
4154 }
4155
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 arch_create_got(f);
4157 hide_special_symbols(f);
4158
Eric Andersen889dd202003-01-23 04:48:34 +00004159#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4160 add_ksymoops_symbols(f, m_filename, m_name);
4161#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4162
Eric Andersen9f16d612000-06-12 23:11:16 +00004163 if (k_new_syscalls)
4164 new_create_module_ksymtab(f);
4165
Erik Andersene49d5ec2000-02-08 19:58:47 +00004166 /* Find current size of the module */
4167 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004168
4169
Erik Andersene49d5ec2000-02-08 19:58:47 +00004170 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004171 if (m_addr == -1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004172 case EEXIST:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004173 bb_error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00004174 goto out;
4175 case ENOMEM:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004176 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00004177 m_size);
4178 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00004179 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +00004180 bb_perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00004181 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004182 }
Erik Andersend387d011999-12-21 02:55:11 +00004183
Eric Andersen8ae319a2001-05-21 16:09:18 +00004184#if !LOADBITS
4185 /*
4186 * the PROGBITS section was not loaded by the obj_load
4187 * now we can load them directly into the kernel memory
4188 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004189 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004190 delete_module(m_name);
4191 goto out;
4192 }
4193#endif
4194
Eric Andersen9f16d612000-06-12 23:11:16 +00004195 if (!obj_relocate(f, m_addr)) {
4196 delete_module(m_name);
4197 goto out;
4198 }
Erik Andersend387d011999-12-21 02:55:11 +00004199
Eric Andersen9f16d612000-06-12 23:11:16 +00004200 if (k_new_syscalls
4201 ? !new_init_module(m_name, f, m_size)
4202 : !old_init_module(m_name, f, m_size))
4203 {
4204 delete_module(m_name);
4205 goto out;
4206 }
4207
Eric Andersenbe65c352003-01-23 04:57:35 +00004208#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4209 if(flag_print_load_map)
4210 print_load_map(f);
4211#endif
4212
Matt Kraai3e856ce2000-12-01 02:55:13 +00004213 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004214
4215out:
Eric Andersen61f83052002-06-22 17:15:42 +00004216#ifdef CONFIG_FEATURE_CLEAN_UP
4217 if(fp)
Erik Andersene49d5ec2000-02-08 19:58:47 +00004218 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004219 if(tmp1) {
4220 free(tmp1);
4221 } else {
4222 free(m_name);
4223 }
4224 free(m_filename);
4225#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004226 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004227}