blob: 5e51fcb709d3a163135d3732c1cbab781d425a23 [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 Andersen4f4bcfc2001-04-25 17:22:32 +00004 * This version of insmod now supports x86, ARM, SH3/4, powerpc, and MIPS.
Erik Andersen02104321999-12-17 18:57:34 +00005 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00006 * Copyright (C) 1999,2000,2001 by Lineo, inc.
Eric Andersen9f16d612000-06-12 23:11:16 +00007 * Written by Erik Andersen <andersen@lineo.com>
8 * and Ron Alder <alder@lineo.com>
9 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000010 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000011 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
12 *
13 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
14 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
15 * very minor changes required to also work with StrongArm and presumably
16 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000017 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000018 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
19 * PowerPC specific code stolen from modutils-2.3.16,
20 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
21 * I've only tested the code on mpc8xx platforms in big-endian mode.
22 * Did some cleanup and added BB_USE_xxx_ENTRIES...
23 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000024 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
25 * based on modutils-2.4.2
26 * MIPS specific support for Elf loading and relocation.
27 * Copyright 1996, 1997 Linux International.
28 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
29 *
Eric Andersen9f16d612000-06-12 23:11:16 +000030 * Based almost entirely on the Linux modutils-2.3.11 implementation.
31 * Copyright 1996, 1997 Linux International.
32 * New implementation contributed by Richard Henderson <rth@tamu.edu>
33 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
34 * Restructured (and partly rewritten) by:
35 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000036 *
37 * This program is free software; you can redistribute it and/or modify
38 * it under the terms of the GNU General Public License as published by
39 * the Free Software Foundation; either version 2 of the License, or
40 * (at your option) any later version.
41 *
42 * This program is distributed in the hope that it will be useful,
43 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45 * General Public License for more details.
46 *
47 * You should have received a copy of the GNU General Public License
48 * along with this program; if not, write to the Free Software
49 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50 *
51 */
52
Erik Andersen02104321999-12-17 18:57:34 +000053#include <stdlib.h>
54#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000055#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000056#include <errno.h>
57#include <unistd.h>
58#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000059#include <ctype.h>
60#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000061#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000062#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000064#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000065
Eric Andersen64c8b172001-04-05 07:33:10 +000066#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
67# define new_sys_init_module init_module
68#else
69# define old_sys_init_module init_module
70#endif
71
Eric Andersen8ae319a2001-05-21 16:09:18 +000072#ifdef BB_FEATURE_INSMOD_LOADINKMEM
73#define LOADBITS 0
74#else
75#define LOADBITS 1
76#endif
77
Eric Andersen90fe7fe2001-02-20 20:47:08 +000078#if defined(__powerpc__)
79#define BB_USE_PLT_ENTRIES
80#define BB_PLT_ENTRY_SIZE 16
81#endif
82
83#if defined(__arm__)
84#define BB_USE_PLT_ENTRIES
85#define BB_PLT_ENTRY_SIZE 8
86#define BB_USE_GOT_ENTRIES
87#define BB_GOT_ENTRY_SIZE 8
88#endif
89
90#if defined(__sh__)
91#define BB_USE_GOT_ENTRIES
92#define BB_GOT_ENTRY_SIZE 4
93#endif
94
95#if defined(__i386__)
96#define BB_USE_GOT_ENTRIES
97#define BB_GOT_ENTRY_SIZE 4
98#endif
99
Eric Andersen2bf658d2001-02-24 20:01:53 +0000100#if defined(__mips__)
101// neither used
102#endif
103
Eric Andersen9f16d612000-06-12 23:11:16 +0000104//----------------------------------------------------------------------------
105//--------modutils module.h, lines 45-242
106//----------------------------------------------------------------------------
107
108/* Definitions for the Linux module syscall interface.
109 Copyright 1996, 1997 Linux International.
110
111 Contributed by Richard Henderson <rth@tamu.edu>
112
113 This file is part of the Linux modutils.
114
115 This program is free software; you can redistribute it and/or modify it
116 under the terms of the GNU General Public License as published by the
117 Free Software Foundation; either version 2 of the License, or (at your
118 option) any later version.
119
120 This program is distributed in the hope that it will be useful, but
121 WITHOUT ANY WARRANTY; without even the implied warranty of
122 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
123 General Public License for more details.
124
125 You should have received a copy of the GNU General Public License
126 along with this program; if not, write to the Free Software Foundation,
127 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
128
129
130#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000131static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000132
Eric Andersen8ae319a2001-05-21 16:09:18 +0000133#ident "$Id: insmod.c,v 1.64 2001/05/21 16:09:18 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000134
135/* This file contains the structures used by the 2.0 and 2.1 kernels.
136 We do not use the kernel headers directly because we do not wish
137 to be dependant on a particular kernel version to compile insmod. */
138
139
140/*======================================================================*/
141/* The structures used by Linux 2.0. */
142
143/* The symbol format used by get_kernel_syms(2). */
144struct old_kernel_sym
145{
146 unsigned long value;
147 char name[60];
148};
149
150struct old_module_ref
151{
152 unsigned long module; /* kernel addresses */
153 unsigned long next;
154};
155
156struct old_module_symbol
157{
158 unsigned long addr;
159 unsigned long name;
160};
161
162struct old_symbol_table
163{
164 int size; /* total, including string table!!! */
165 int n_symbols;
166 int n_refs;
167 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
168 struct old_module_ref ref[0]; /* actual size defined by n_refs */
169};
170
171struct old_mod_routines
172{
173 unsigned long init;
174 unsigned long cleanup;
175};
176
177struct old_module
178{
179 unsigned long next;
180 unsigned long ref; /* the list of modules that refer to me */
181 unsigned long symtab;
182 unsigned long name;
183 int size; /* size of module in pages */
184 unsigned long addr; /* address of module */
185 int state;
186 unsigned long cleanup; /* cleanup routine */
187};
188
189/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000190static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000191
192int get_kernel_syms(struct old_kernel_sym *);
193int old_sys_init_module(const char *name, char *code, unsigned codesize,
194 struct old_mod_routines *, struct old_symbol_table *);
195
196/*======================================================================*/
197/* For sizeof() which are related to the module platform and not to the
198 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
199
200#define tgt_sizeof_char sizeof(char)
201#define tgt_sizeof_short sizeof(short)
202#define tgt_sizeof_int sizeof(int)
203#define tgt_sizeof_long sizeof(long)
204#define tgt_sizeof_char_p sizeof(char *)
205#define tgt_sizeof_void_p sizeof(void *)
206#define tgt_long long
207
208#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
209#undef tgt_sizeof_long
210#undef tgt_sizeof_char_p
211#undef tgt_sizeof_void_p
212#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000213static const int tgt_sizeof_long = 8;
214static const int tgt_sizeof_char_p = 8;
215static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000216#define tgt_long long long
217#endif
218
219/*======================================================================*/
220/* The structures used in Linux 2.1. */
221
222/* Note: new_module_symbol does not use tgt_long intentionally */
223struct new_module_symbol
224{
225 unsigned long value;
226 unsigned long name;
227};
228
229struct new_module_persist;
230
231struct new_module_ref
232{
233 unsigned tgt_long dep; /* kernel addresses */
234 unsigned tgt_long ref;
235 unsigned tgt_long next_ref;
236};
237
238struct new_module
239{
240 unsigned tgt_long size_of_struct; /* == sizeof(module) */
241 unsigned tgt_long next;
242 unsigned tgt_long name;
243 unsigned tgt_long size;
244
245 tgt_long usecount;
246 unsigned tgt_long flags; /* AUTOCLEAN et al */
247
248 unsigned nsyms;
249 unsigned ndeps;
250
251 unsigned tgt_long syms;
252 unsigned tgt_long deps;
253 unsigned tgt_long refs;
254 unsigned tgt_long init;
255 unsigned tgt_long cleanup;
256 unsigned tgt_long ex_table_start;
257 unsigned tgt_long ex_table_end;
258#ifdef __alpha__
259 unsigned tgt_long gp;
260#endif
261 /* Everything after here is extension. */
262 unsigned tgt_long persist_start;
263 unsigned tgt_long persist_end;
264 unsigned tgt_long can_unload;
265 unsigned tgt_long runsize;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000266#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
267 const char *kallsyms_start; /* All symbols for kernel debugging */
268 const char *kallsyms_end;
269 const char *archdata_start; /* arch specific data for module */
270 const char *archdata_end;
271 const char *kernel_data; /* Reserved for kernel internal use */
272#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000273};
274
Eric Andersen8ae319a2001-05-21 16:09:18 +0000275#define ARCHDATA_SEC_NAME "__archdata"
276#define KALLSYMS_SEC_NAME "__kallsyms"
277
278
Eric Andersen9f16d612000-06-12 23:11:16 +0000279struct new_module_info
280{
281 unsigned long addr;
282 unsigned long size;
283 unsigned long flags;
284 long usecount;
285};
286
287/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000288static const int NEW_MOD_RUNNING = 1;
289static const int NEW_MOD_DELETED = 2;
290static const int NEW_MOD_AUTOCLEAN = 4;
291static const int NEW_MOD_VISITED = 8;
292static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000293
Eric Andersen64c8b172001-04-05 07:33:10 +0000294int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000295int query_module(const char *name, int which, void *buf, size_t bufsize,
296 size_t *ret);
297
298/* Values for query_module's which. */
299
Mark Whitley59ab0252001-01-23 22:30:04 +0000300static const int QM_MODULES = 1;
301static const int QM_DEPS = 2;
302static const int QM_REFS = 3;
303static const int QM_SYMBOLS = 4;
304static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000305
306/*======================================================================*/
307/* The system calls unchanged between 2.0 and 2.1. */
308
309unsigned long create_module(const char *, size_t);
310int delete_module(const char *);
311
312
313#endif /* module.h */
314
315//----------------------------------------------------------------------------
316//--------end of modutils module.h
317//----------------------------------------------------------------------------
318
319
320
321//----------------------------------------------------------------------------
322//--------modutils obj.h, lines 253-462
323//----------------------------------------------------------------------------
324
325/* Elf object file loading and relocation routines.
326 Copyright 1996, 1997 Linux International.
327
328 Contributed by Richard Henderson <rth@tamu.edu>
329
330 This file is part of the Linux modutils.
331
332 This program is free software; you can redistribute it and/or modify it
333 under the terms of the GNU General Public License as published by the
334 Free Software Foundation; either version 2 of the License, or (at your
335 option) any later version.
336
337 This program is distributed in the hope that it will be useful, but
338 WITHOUT ANY WARRANTY; without even the implied warranty of
339 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
340 General Public License for more details.
341
342 You should have received a copy of the GNU General Public License
343 along with this program; if not, write to the Free Software Foundation,
344 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
345
346
347#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000348static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000349
Eric Andersen8ae319a2001-05-21 16:09:18 +0000350#ident "$Id: insmod.c,v 1.64 2001/05/21 16:09:18 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000351
352/* The relocatable object is manipulated using elfin types. */
353
354#include <stdio.h>
355#include <elf.h>
356
357
358/* Machine-specific elf macros for i386 et al. */
359
Eric Andersenfe4208f2000-09-24 03:44:29 +0000360/* the SH changes have only been tested on the SH4 in =little endian= mode */
361/* I'm not sure about big endian, so let's warn: */
362
363#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
364#error insmod.c may require changes for use on big endian SH4/SH3
365#endif
366
367/* it may or may not work on the SH1/SH2... So let's error on those
368 also */
369#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
370#error insmod.c may require changes for non-SH3/SH4 use
371#endif
372
Eric Andersen9f16d612000-06-12 23:11:16 +0000373#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000374
Eric Andersen8ae319a2001-05-21 16:09:18 +0000375#if (defined(__m68k__))
376#define ELFDATAM ELFDATA2MSB
377#else
378#define ELFDATAM ELFDATA2LSB
379#endif
380
381
382
Eric Andersenfe4208f2000-09-24 03:44:29 +0000383#if defined(__sh__)
384
385#define MATCH_MACHINE(x) (x == EM_SH)
386#define SHT_RELM SHT_RELA
387#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000388#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000389
Eric Andersen21adca72000-12-06 18:18:26 +0000390#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000391
Eric Andersen21adca72000-12-06 18:18:26 +0000392#define MATCH_MACHINE(x) (x == EM_ARM)
393#define SHT_RELM SHT_REL
394#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000395#define ELFDATAM ELFDATA2LSB
396
397#elif defined(__powerpc__)
398
399#define MATCH_MACHINE(x) (x == EM_PPC)
400#define SHT_RELM SHT_RELA
401#define Elf32_RelM Elf32_Rela
402#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000403
Eric Andersen2bf658d2001-02-24 20:01:53 +0000404#elif defined(__mips__)
405
Eric Andersen82bb8a22001-03-22 19:01:16 +0000406/* Account for ELF spec changes. */
407#ifndef EM_MIPS_RS3_LE
408#ifdef EM_MIPS_RS4_BE
409#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
410#else
411#define EM_MIPS_RS3_LE 10
412#endif
413#endif /* !EM_MIPS_RS3_LE */
414
Eric Andersen2bf658d2001-02-24 20:01:53 +0000415#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
416#define SHT_RELM SHT_REL
417#define Elf32_RelM Elf32_Rel
418#ifdef __MIPSEB__
419#define ELFDATAM ELFDATA2MSB
420#endif
421#ifdef __MIPSEL__
422#define ELFDATAM ELFDATA2LSB
423#endif
424
Eric Andersen21adca72000-12-06 18:18:26 +0000425#elif defined(__i386__)
426
427/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000428/* this is the previous behavior, but it does result in
429 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000430#ifndef EM_486
431#define MATCH_MACHINE(x) (x == EM_386)
432#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000433#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000434#endif
435
Eric Andersen9f16d612000-06-12 23:11:16 +0000436#define SHT_RELM SHT_REL
437#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000438#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000439
Eric Andersen8ae319a2001-05-21 16:09:18 +0000440#elif defined(__m68k__)
441
442#define MATCH_MACHINE(x) (x == EM_68K)
443#define SHT_RELM SHT_RELA
444#define Elf32_RelM Elf32_Rela
445
Eric Andersen21adca72000-12-06 18:18:26 +0000446#else
Eric Andersend5cad142001-01-26 02:23:57 +0000447#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000448#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000449
450#ifndef ElfW
451# if ELFCLASSM == ELFCLASS32
452# define ElfW(x) Elf32_ ## x
453# define ELFW(x) ELF32_ ## x
454# else
455# define ElfW(x) Elf64_ ## x
456# define ELFW(x) ELF64_ ## x
457# endif
458#endif
459
460/* For some reason this is missing from libc5. */
461#ifndef ELF32_ST_INFO
462# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
463#endif
464
465#ifndef ELF64_ST_INFO
466# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
467#endif
468
469struct obj_string_patch;
470struct obj_symbol_patch;
471
472struct obj_section
473{
474 ElfW(Shdr) header;
475 const char *name;
476 char *contents;
477 struct obj_section *load_next;
478 int idx;
479};
480
481struct obj_symbol
482{
483 struct obj_symbol *next; /* hash table link */
484 const char *name;
485 unsigned long value;
486 unsigned long size;
487 int secidx; /* the defining section index/module */
488 int info;
489 int ksymidx; /* for export to the kernel symtab */
490 int referenced; /* actually used in the link */
491};
492
493/* Hardcode the hash table size. We shouldn't be needing so many
494 symbols that we begin to degrade performance, and we get a big win
495 by giving the compiler a constant divisor. */
496
497#define HASH_BUCKETS 521
498
499struct obj_file
500{
501 ElfW(Ehdr) header;
502 ElfW(Addr) baseaddr;
503 struct obj_section **sections;
504 struct obj_section *load_order;
505 struct obj_section **load_order_search_start;
506 struct obj_string_patch *string_patches;
507 struct obj_symbol_patch *symbol_patches;
508 int (*symbol_cmp)(const char *, const char *);
509 unsigned long (*symbol_hash)(const char *);
510 unsigned long local_symtab_size;
511 struct obj_symbol **local_symtab;
512 struct obj_symbol *symtab[HASH_BUCKETS];
513};
514
515enum obj_reloc
516{
517 obj_reloc_ok,
518 obj_reloc_overflow,
519 obj_reloc_dangerous,
520 obj_reloc_unhandled
521};
522
523struct obj_string_patch
524{
525 struct obj_string_patch *next;
526 int reloc_secidx;
527 ElfW(Addr) reloc_offset;
528 ElfW(Addr) string_offset;
529};
530
531struct obj_symbol_patch
532{
533 struct obj_symbol_patch *next;
534 int reloc_secidx;
535 ElfW(Addr) reloc_offset;
536 struct obj_symbol *sym;
537};
538
539
540/* Generic object manipulation routines. */
541
542unsigned long obj_elf_hash(const char *);
543
544unsigned long obj_elf_hash_n(const char *, unsigned long len);
545
546struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
547 unsigned long symidx, int info, int secidx,
548 ElfW(Addr) value, unsigned long size);
549
550struct obj_symbol *obj_find_symbol (struct obj_file *f,
551 const char *name);
552
553ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
554 struct obj_symbol *sym);
555
556void obj_set_symbol_compare(struct obj_file *f,
557 int (*cmp)(const char *, const char *),
558 unsigned long (*hash)(const char *));
559
560struct obj_section *obj_find_section (struct obj_file *f,
561 const char *name);
562
563void obj_insert_section_load_order (struct obj_file *f,
564 struct obj_section *sec);
565
566struct obj_section *obj_create_alloced_section (struct obj_file *f,
567 const char *name,
568 unsigned long align,
569 unsigned long size);
570
571struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
572 const char *name,
573 unsigned long align,
574 unsigned long size);
575
576void *obj_extend_section (struct obj_section *sec, unsigned long more);
577
578int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
579 const char *string);
580
581int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
582 struct obj_symbol *sym);
583
584int obj_check_undefineds(struct obj_file *f);
585
586void obj_allocate_commons(struct obj_file *f);
587
588unsigned long obj_load_size (struct obj_file *f);
589
590int obj_relocate (struct obj_file *f, ElfW(Addr) base);
591
Eric Andersen8ae319a2001-05-21 16:09:18 +0000592struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000593
594int obj_create_image (struct obj_file *f, char *image);
595
596/* Architecture specific manipulation routines. */
597
598struct obj_file *arch_new_file (void);
599
600struct obj_section *arch_new_section (void);
601
602struct obj_symbol *arch_new_symbol (void);
603
604enum obj_reloc arch_apply_relocation (struct obj_file *f,
605 struct obj_section *targsec,
606 struct obj_section *symsec,
607 struct obj_symbol *sym,
608 ElfW(RelM) *rel, ElfW(Addr) value);
609
610int arch_create_got (struct obj_file *f);
611
612struct new_module;
613int arch_init_module (struct obj_file *f, struct new_module *);
614
615#endif /* obj.h */
616//----------------------------------------------------------------------------
617//--------end of modutils obj.h
618//----------------------------------------------------------------------------
619
620
621
622
Erik Andersen02104321999-12-17 18:57:34 +0000623
Erik Andersend387d011999-12-21 02:55:11 +0000624#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000625static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000626
Eric Andersen9f16d612000-06-12 23:11:16 +0000627/*======================================================================*/
628
629int flag_force_load = 0;
630int flag_autoclean = 0;
631int flag_verbose = 0;
632int flag_export = 1;
633
634
635/*======================================================================*/
636
Eric Andersenfe4208f2000-09-24 03:44:29 +0000637/* previously, these were named i386_* but since we could be
638 compiling for the sh, I've renamed them to the more general
639 arch_* These structures are the same between the x86 and SH,
640 and we can't support anything else right now anyway. In the
641 future maybe they should be #if defined'd */
642
Eric Andersen21adca72000-12-06 18:18:26 +0000643/* Done ;-) */
644
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000645
646
647#if defined(BB_USE_PLT_ENTRIES)
648struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000649{
650 int offset;
651 int allocated:1;
652 int inited:1; /* has been set up */
653};
654#endif
655
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000656#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000657struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000658 int offset;
659 unsigned offset_done:1;
660 unsigned reloc_done:1;
661};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000662#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000663
Eric Andersen2bf658d2001-02-24 20:01:53 +0000664#if defined(__mips__)
665struct mips_hi16
666{
667 struct mips_hi16 *next;
668 Elf32_Addr *addr;
669 Elf32_Addr value;
670};
671#endif
672
Eric Andersenfe4208f2000-09-24 03:44:29 +0000673struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000674 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000675#if defined(BB_USE_PLT_ENTRIES)
676 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000677#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000678#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000679 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000680#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000681#if defined(__mips__)
682 struct mips_hi16 *mips_hi16_list;
683#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000684};
685
Eric Andersenfe4208f2000-09-24 03:44:29 +0000686struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000687 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000688#if defined(BB_USE_PLT_ENTRIES)
689 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000690#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000691#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000692 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000693#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000694};
695
696
Eric Andersen9f16d612000-06-12 23:11:16 +0000697struct external_module {
698 const char *name;
699 ElfW(Addr) addr;
700 int used;
701 size_t nsyms;
702 struct new_module_symbol *syms;
703};
704
705struct new_module_symbol *ksyms;
706size_t nksyms;
707
708struct external_module *ext_modules;
709int n_ext_modules;
710int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000711extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000712
Eric Andersen14d35432001-05-14 17:07:32 +0000713static char m_filename[FILENAME_MAX + 1];
714static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000715
Eric Andersenfe4208f2000-09-24 03:44:29 +0000716
Erik Andersen02104321999-12-17 18:57:34 +0000717
Eric Andersen9f16d612000-06-12 23:11:16 +0000718/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000719
Eric Andersen9f16d612000-06-12 23:11:16 +0000720
Eric Andersen14d35432001-05-14 17:07:32 +0000721static int check_module_name_match(const char *filename, struct stat *statbuf,
722 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000723{
Eric Andersen14d35432001-05-14 17:07:32 +0000724 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000725
Eric Andersen14d35432001-05-14 17:07:32 +0000726 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000727 return (FALSE);
728 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000729 char *tmp, *tmp1 = strdup(filename);
730 tmp = get_last_path_component(tmp1);
731 if (strcmp(tmp, fullname) == 0) {
732 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000733 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000734 safe_strncpy(m_filename, filename, sizeof(m_filename));
735 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000736 }
Eric Andersen14d35432001-05-14 17:07:32 +0000737 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000738 }
Eric Andersen14d35432001-05-14 17:07:32 +0000739 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000740}
741
Erik Andersen02104321999-12-17 18:57:34 +0000742
Eric Andersen9f16d612000-06-12 23:11:16 +0000743/*======================================================================*/
744
745struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000746{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000747 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000748 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000749
750#if defined(BB_USE_PLT_ENTRIES)
751 f->plt = NULL;
752#endif
753#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000756#if defined(__mips__)
757 f->mips_hi16_list = NULL;
758#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000759
Eric Andersen9f16d612000-06-12 23:11:16 +0000760 return &f->root;
761}
762
763struct obj_section *arch_new_section(void)
764{
765 return xmalloc(sizeof(struct obj_section));
766}
767
768struct obj_symbol *arch_new_symbol(void)
769{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000770 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000771 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000772
773#if defined(BB_USE_PLT_ENTRIES)
774 memset(&sym->pltent, 0, sizeof(sym->pltent));
775#endif
776#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000777 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000778#endif
779
Eric Andersen9f16d612000-06-12 23:11:16 +0000780 return &sym->root;
781}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000782
Eric Andersen9f16d612000-06-12 23:11:16 +0000783enum obj_reloc
784arch_apply_relocation(struct obj_file *f,
785 struct obj_section *targsec,
786 struct obj_section *symsec,
787 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000788 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000789{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000791#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000792 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000793#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000794
Eric Andersen21adca72000-12-06 18:18:26 +0000795 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
796 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000797#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000798 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000799#endif
800#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000801 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000802 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000803 unsigned long *ip;
804#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000805 enum obj_reloc ret = obj_reloc_ok;
806
807 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000808
809/* even though these constants seem to be the same for
810 the i386 and the sh, we "#if define" them for clarity
811 and in case that ever changes */
812#if defined(__sh__)
813 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000814#elif defined(__arm__)
815 case R_ARM_NONE:
816#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000817 case R_386_NONE:
Eric Andersen8ae319a2001-05-21 16:09:18 +0000818#elif defined(__m68k__)
819 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000820#elif defined(__powerpc__)
821 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000822#elif defined(__mips__)
823 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000824#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000825 break;
826
Eric Andersenfe4208f2000-09-24 03:44:29 +0000827#if defined(__sh__)
828 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000829#elif defined(__arm__)
830 case R_ARM_ABS32:
831#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000832 case R_386_32:
Eric Andersen8ae319a2001-05-21 16:09:18 +0000833#elif defined(__m68k__)
834 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000835#elif defined(__powerpc__)
836 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000837#elif defined(__mips__)
838 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000839#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000840 *loc += v;
841 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000842#if defined(__m68k__)
843 case R_68K_8:
844 if (v > 0xff)
845 ret = obj_reloc_overflow;
846 *(char *)loc = v;
847 break;
848 case R_68K_16:
849 if (v > 0xffff)
850 ret = obj_reloc_overflow;
851 *(short *)loc = v;
852 break;
853#endif /* __m68k__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000854
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000855#if defined(__powerpc__)
856 case R_PPC_ADDR16_HA:
857 *(unsigned short *)loc = (v + 0x8000) >> 16;
858 break;
859
860 case R_PPC_ADDR16_HI:
861 *(unsigned short *)loc = v >> 16;
862 break;
863
864 case R_PPC_ADDR16_LO:
865 *(unsigned short *)loc = v;
866 break;
867#endif
868
Eric Andersen2bf658d2001-02-24 20:01:53 +0000869#if defined(__mips__)
870 case R_MIPS_26:
871 if (v % 4)
872 ret = obj_reloc_dangerous;
873 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
874 ret = obj_reloc_overflow;
875 *loc =
876 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
877 0x03ffffff);
878 break;
879
880 case R_MIPS_HI16:
881 {
882 struct mips_hi16 *n;
883
884 /* We cannot relocate this one now because we don't know the value
885 of the carry we need to add. Save the information, and let LO16
886 do the actual relocation. */
887 n = (struct mips_hi16 *) xmalloc(sizeof *n);
888 n->addr = loc;
889 n->value = v;
890 n->next = ifile->mips_hi16_list;
891 ifile->mips_hi16_list = n;
892 break;
893 }
894
895 case R_MIPS_LO16:
896 {
897 unsigned long insnlo = *loc;
898 Elf32_Addr val, vallo;
899
900 /* Sign extend the addend we extract from the lo insn. */
901 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
902
903 if (ifile->mips_hi16_list != NULL) {
904 struct mips_hi16 *l;
905
906 l = ifile->mips_hi16_list;
907 while (l != NULL) {
908 struct mips_hi16 *next;
909 unsigned long insn;
910
911 /* The value for the HI16 had best be the same. */
912 assert(v == l->value);
913
914 /* Do the HI16 relocation. Note that we actually don't
915 need to know anything about the LO16 itself, except where
916 to find the low 16 bits of the addend needed by the LO16. */
917 insn = *l->addr;
918 val =
919 ((insn & 0xffff) << 16) +
920 vallo;
921 val += v;
922
923 /* Account for the sign extension that will happen in the
924 low bits. */
925 val =
926 ((val >> 16) +
927 ((val & 0x8000) !=
928 0)) & 0xffff;
929
930 insn = (insn & ~0xffff) | val;
931 *l->addr = insn;
932
933 next = l->next;
934 free(l);
935 l = next;
936 }
937
938 ifile->mips_hi16_list = NULL;
939 }
940
941 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
942 val = v + vallo;
943 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
944 *loc = insnlo;
945 break;
946 }
947#endif
948
Eric Andersen21adca72000-12-06 18:18:26 +0000949#if defined(__arm__)
950#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000951 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000952 *loc += v - dot;
953 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000954#elif defined(__i386__)
955 case R_386_PLT32:
956 case R_386_PC32:
957 *loc += v - dot;
958 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000959#elif defined(__m68k__)
960 case R_68K_PC8:
961 v -= dot;
962 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
963 ret = obj_reloc_overflow;
964 *(char *)loc = v;
965 break;
966 case R_68K_PC16:
967 v -= dot;
968 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
969 ret = obj_reloc_overflow;
970 *(short *)loc = v;
971 break;
972 case R_68K_PC32:
973 *(int *)loc = v - dot;
974 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000975#elif defined(__powerpc__)
976 case R_PPC_REL32:
977 *loc = v - dot;
978 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000979#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000980
Eric Andersenfe4208f2000-09-24 03:44:29 +0000981#if defined(__sh__)
982 case R_SH_PLT32:
983 *loc = v - dot;
984 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000985#elif defined(__i386__)
986#endif
987
988#if defined(BB_USE_PLT_ENTRIES)
989
990#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000991 case R_ARM_PC24:
992 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000993#endif
994#if defined(__powerpc__)
995 case R_PPC_REL24:
996#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000997 /* find the plt entry and initialize it if necessary */
998 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000999
1000 pe = (struct arch_plt_entry*) &isym->pltent;
1001
Eric Andersen21adca72000-12-06 18:18:26 +00001002 if (! pe->inited) {
1003 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001004
1005 /* generate some machine code */
1006
1007#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001008 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1009 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001010#endif
1011#if defined(__powerpc__)
1012 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1013 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1014 ip[2] = 0x7d6903a6; /* mtctr r11 */
1015 ip[3] = 0x4e800420; /* bctr */
1016#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001017 pe->inited = 1;
1018 }
1019
1020 /* relative distance to target */
1021 v -= dot;
1022 /* if the target is too far away.... */
1023 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1024 /* go via the plt */
1025 v = plt + pe->offset - dot;
1026 }
1027 if (v & 3)
1028 ret = obj_reloc_dangerous;
1029
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001030 /* merge the offset into the instruction. */
1031#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001032 /* Convert to words. */
1033 v >>= 2;
1034
Eric Andersen21adca72000-12-06 18:18:26 +00001035 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001036#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001037#if defined(__powerpc__)
1038 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1039#endif
1040 break;
1041#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001042
Eric Andersen21adca72000-12-06 18:18:26 +00001043#if defined(__arm__)
1044#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001045 case R_SH_GLOB_DAT:
1046 case R_SH_JMP_SLOT:
1047 *loc = v;
1048 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001049#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001050 case R_386_GLOB_DAT:
1051 case R_386_JMP_SLOT:
1052 *loc = v;
1053 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001054#elif defined(__m68k__)
1055 case R_68K_GLOB_DAT:
1056 case R_68K_JMP_SLOT:
1057 *loc = v;
1058 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001059#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001060
Eric Andersen21adca72000-12-06 18:18:26 +00001061#if defined(__arm__)
1062#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001063 case R_SH_RELATIVE:
1064 *loc += f->baseaddr + rel->r_addend;
1065 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001066#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001067 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001068 *loc += f->baseaddr;
1069 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001070#elif defined(__m68k__)
1071 case R_68K_RELATIVE:
1072 *(int *)loc += f->baseaddr;
1073 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001074#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001075
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001076#if defined(BB_USE_GOT_ENTRIES)
1077
Eric Andersen8ae319a2001-05-21 16:09:18 +00001078#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001079#if defined(__sh__)
1080 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001081#elif defined(__arm__)
1082 case R_ARM_GOTPC:
1083#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001084 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001085#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001086 assert(got != 0);
1087#if defined(__sh__)
1088 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001089#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001090 *loc += got - dot;
1091#endif
1092 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001093#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001094
Eric Andersenfe4208f2000-09-24 03:44:29 +00001095#if defined(__sh__)
1096 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001097#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001098 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001099#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001100 case R_386_GOT32:
Eric Andersen8ae319a2001-05-21 16:09:18 +00001101#elif defined(__m68k__)
1102 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001103#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001104 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001105 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001106 if (!isym->gotent.reloc_done) {
1107 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001108 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001109 }
Eric Andersen21adca72000-12-06 18:18:26 +00001110 /* make the reloc with_respect_to_.got */
1111#if defined(__sh__)
1112 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001113#elif defined(__i386__) || defined(__arm__) || defined(__m68k__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001114 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001115#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001116 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001117
Eric Andersen21adca72000-12-06 18:18:26 +00001118 /* address relative to the got */
Eric Andersen8ae319a2001-05-21 16:09:18 +00001119#if !defined(__m68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001120#if defined(__sh__)
1121 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001122#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001123 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001124#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001125 case R_386_GOTOFF:
Eric Andersen8ae319a2001-05-21 16:09:18 +00001126#elif defined(__m68k__)
1127 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001128#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001129 assert(got != 0);
1130 *loc += v - got;
1131 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001132#endif // __m68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001133
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001134#endif /* BB_USE_GOT_ENTRIES */
1135
Eric Andersen9f16d612000-06-12 23:11:16 +00001136 default:
Eric Andersen21125542000-12-13 16:41:29 +00001137 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001138 ret = obj_reloc_unhandled;
1139 break;
1140 }
1141
1142 return ret;
1143}
1144
1145int arch_create_got(struct obj_file *f)
1146{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001147#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001148 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001149 int i;
1150#if defined(BB_USE_GOT_ENTRIES)
1151 int got_offset = 0, gotneeded = 0;
1152#endif
1153#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001154 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001155#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001156 struct obj_section *relsec, *symsec, *strsec;
1157 ElfW(RelM) *rel, *relend;
1158 ElfW(Sym) *symtab, *extsym;
1159 const char *strtab, *name;
1160 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001161
Eric Andersen21adca72000-12-06 18:18:26 +00001162 for (i = 0; i < f->header.e_shnum; ++i) {
1163 relsec = f->sections[i];
1164 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001165 continue;
1166
Eric Andersen21adca72000-12-06 18:18:26 +00001167 symsec = f->sections[relsec->header.sh_link];
1168 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001169
Eric Andersen21adca72000-12-06 18:18:26 +00001170 rel = (ElfW(RelM) *) relsec->contents;
1171 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1172 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001173 strtab = (const char *) strsec->contents;
1174
1175 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001176 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001177
1178 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001179#if defined(__arm__)
1180 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001181 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001182#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001183 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001184 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001185#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001186 case R_386_GOT32:
1187 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001188#elif defined(__m68k__)
1189 case R_68K_GOT32:
1190 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001191#endif
1192
1193#if defined(__powerpc__)
1194 case R_PPC_REL24:
1195 pltneeded = 1;
1196 break;
1197#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001198
1199#if defined(__arm__)
1200 case R_ARM_PC24:
1201 case R_ARM_PLT32:
1202 pltneeded = 1;
1203 break;
1204
1205 case R_ARM_GOTPC:
1206 case R_ARM_GOTOFF:
1207 gotneeded = 1;
1208 if (got_offset == 0)
1209 got_offset = 4;
1210#elif defined(__sh__)
1211 case R_SH_GOTPC:
1212 case R_SH_GOTOFF:
1213 gotneeded = 1;
1214#elif defined(__i386__)
1215 case R_386_GOTPC:
1216 case R_386_GOTOFF:
1217 gotneeded = 1;
1218#endif
1219
1220 default:
1221 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001222 }
1223
Eric Andersen21adca72000-12-06 18:18:26 +00001224 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001225 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001226 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001227 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001228 }
1229 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001230#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001231 if (!intsym->gotent.offset_done) {
1232 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001233 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001234 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001235 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001236#endif
1237#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001238 if (pltneeded && intsym->pltent.allocated == 0) {
1239 intsym->pltent.allocated = 1;
1240 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001241 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001242 intsym->pltent.inited = 0;
1243 pltneeded = 0;
1244 }
1245#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001246 }
1247 }
Eric Andersen21adca72000-12-06 18:18:26 +00001248
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001249#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001250 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001251 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001252
Eric Andersene76c3b02001-04-05 03:14:39 +00001253 if (myrelsec) {
1254 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001255 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001256 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001257 BB_GOT_ENTRY_SIZE,
1258 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001259 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001260 }
1261
Eric Andersene76c3b02001-04-05 03:14:39 +00001262 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001263 }
Eric Andersen21adca72000-12-06 18:18:26 +00001264#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001265
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001266#if defined(BB_USE_PLT_ENTRIES)
1267 if (plt_offset)
1268 ifile->plt = obj_create_alloced_section(f, ".plt",
1269 BB_PLT_ENTRY_SIZE,
1270 plt_offset);
1271#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001272#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001273 return 1;
1274}
1275
1276int arch_init_module(struct obj_file *f, struct new_module *mod)
1277{
1278 return 1;
1279}
1280
1281
1282/*======================================================================*/
1283
1284/* Standard ELF hash function. */
1285inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1286{
1287 unsigned long h = 0;
1288 unsigned long g;
1289 unsigned char ch;
1290
1291 while (n > 0) {
1292 ch = *name++;
1293 h = (h << 4) + ch;
1294 if ((g = (h & 0xf0000000)) != 0) {
1295 h ^= g >> 24;
1296 h &= ~g;
1297 }
1298 n--;
1299 }
1300 return h;
1301}
1302
1303unsigned long obj_elf_hash(const char *name)
1304{
1305 return obj_elf_hash_n(name, strlen(name));
1306}
1307
1308#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1309/* Get the kernel version in the canonical integer form. */
1310
1311static int get_kernel_version(char str[STRVERSIONLEN])
1312{
1313 struct utsname uts_info;
1314 char *p, *q;
1315 int a, b, c;
1316
1317 if (uname(&uts_info) < 0)
1318 return -1;
1319 strncpy(str, uts_info.release, STRVERSIONLEN);
1320 p = uts_info.release;
1321
1322 a = strtoul(p, &p, 10);
1323 if (*p != '.')
1324 return -1;
1325 b = strtoul(p + 1, &p, 10);
1326 if (*p != '.')
1327 return -1;
1328 c = strtoul(p + 1, &q, 10);
1329 if (p + 1 == q)
1330 return -1;
1331
1332 return a << 16 | b << 8 | c;
1333}
1334
1335/* String comparison for non-co-versioned kernel and module. */
1336
1337static int ncv_strcmp(const char *a, const char *b)
1338{
1339 size_t alen = strlen(a), blen = strlen(b);
1340
1341 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1342 return strncmp(a, b, alen);
1343 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1344 return strncmp(a, b, blen);
1345 else
1346 return strcmp(a, b);
1347}
1348
1349/* String hashing for non-co-versioned kernel and module. Here
1350 we are simply forced to drop the crc from the hash. */
1351
1352static unsigned long ncv_symbol_hash(const char *str)
1353{
1354 size_t len = strlen(str);
1355 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1356 len -= 10;
1357 return obj_elf_hash_n(str, len);
1358}
1359
1360void
1361obj_set_symbol_compare(struct obj_file *f,
1362 int (*cmp) (const char *, const char *),
1363 unsigned long (*hash) (const char *))
1364{
1365 if (cmp)
1366 f->symbol_cmp = cmp;
1367 if (hash) {
1368 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1369 int i;
1370
1371 f->symbol_hash = hash;
1372
1373 memcpy(tmptab, f->symtab, sizeof(tmptab));
1374 memset(f->symtab, 0, sizeof(f->symtab));
1375
1376 for (i = 0; i < HASH_BUCKETS; ++i)
1377 for (sym = tmptab[i]; sym; sym = next) {
1378 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1379 next = sym->next;
1380 sym->next = f->symtab[h];
1381 f->symtab[h] = sym;
1382 }
1383 }
1384}
1385
1386#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1387
1388
1389struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1390 unsigned long symidx, int info,
1391 int secidx, ElfW(Addr) value,
1392 unsigned long size)
1393{
1394 struct obj_symbol *sym;
1395 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1396 int n_type = ELFW(ST_TYPE) (info);
1397 int n_binding = ELFW(ST_BIND) (info);
1398
1399 for (sym = f->symtab[hash]; sym; sym = sym->next)
1400 if (f->symbol_cmp(sym->name, name) == 0) {
1401 int o_secidx = sym->secidx;
1402 int o_info = sym->info;
1403 int o_type = ELFW(ST_TYPE) (o_info);
1404 int o_binding = ELFW(ST_BIND) (o_info);
1405
1406 /* A redefinition! Is it legal? */
1407
1408 if (secidx == SHN_UNDEF)
1409 return sym;
1410 else if (o_secidx == SHN_UNDEF)
1411 goto found;
1412 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1413 /* Cope with local and global symbols of the same name
1414 in the same object file, as might have been created
1415 by ld -r. The only reason locals are now seen at this
1416 level at all is so that we can do semi-sensible things
1417 with parameters. */
1418
1419 struct obj_symbol *nsym, **p;
1420
1421 nsym = arch_new_symbol();
1422 nsym->next = sym->next;
1423 nsym->ksymidx = -1;
1424
1425 /* Excise the old (local) symbol from the hash chain. */
1426 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1427 continue;
1428 *p = sym = nsym;
1429 goto found;
1430 } else if (n_binding == STB_LOCAL) {
1431 /* Another symbol of the same name has already been defined.
1432 Just add this to the local table. */
1433 sym = arch_new_symbol();
1434 sym->next = NULL;
1435 sym->ksymidx = -1;
1436 f->local_symtab[symidx] = sym;
1437 goto found;
1438 } else if (n_binding == STB_WEAK)
1439 return sym;
1440 else if (o_binding == STB_WEAK)
1441 goto found;
1442 /* Don't unify COMMON symbols with object types the programmer
1443 doesn't expect. */
1444 else if (secidx == SHN_COMMON
1445 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1446 return sym;
1447 else if (o_secidx == SHN_COMMON
1448 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1449 goto found;
1450 else {
1451 /* Don't report an error if the symbol is coming from
1452 the kernel or some external module. */
1453 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001454 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001455 return sym;
1456 }
1457 }
1458
1459 /* Completely new symbol. */
1460 sym = arch_new_symbol();
1461 sym->next = f->symtab[hash];
1462 f->symtab[hash] = sym;
1463 sym->ksymidx = -1;
1464
1465 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1466 f->local_symtab[symidx] = sym;
1467
1468 found:
1469 sym->name = name;
1470 sym->value = value;
1471 sym->size = size;
1472 sym->secidx = secidx;
1473 sym->info = info;
1474
1475 return sym;
1476}
1477
1478struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1479{
1480 struct obj_symbol *sym;
1481 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1482
1483 for (sym = f->symtab[hash]; sym; sym = sym->next)
1484 if (f->symbol_cmp(sym->name, name) == 0)
1485 return sym;
1486
1487 return NULL;
1488}
1489
1490ElfW(Addr)
1491 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1492{
1493 if (sym) {
1494 if (sym->secidx >= SHN_LORESERVE)
1495 return sym->value;
1496
1497 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1498 } else {
1499 /* As a special case, a NULL sym has value zero. */
1500 return 0;
1501 }
1502}
1503
1504struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1505{
1506 int i, n = f->header.e_shnum;
1507
1508 for (i = 0; i < n; ++i)
1509 if (strcmp(f->sections[i]->name, name) == 0)
1510 return f->sections[i];
1511
1512 return NULL;
1513}
1514
1515static int obj_load_order_prio(struct obj_section *a)
1516{
1517 unsigned long af, ac;
1518
1519 af = a->header.sh_flags;
1520
1521 ac = 0;
1522 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1523 strcmp(a->name + 5, ".init"))
1524 ac |= 32;
1525 if (af & SHF_ALLOC)
1526 ac |= 16;
1527 if (!(af & SHF_WRITE))
1528 ac |= 8;
1529 if (af & SHF_EXECINSTR)
1530 ac |= 4;
1531 if (a->header.sh_type != SHT_NOBITS)
1532 ac |= 2;
1533
1534 return ac;
1535}
1536
1537void
1538obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1539{
1540 struct obj_section **p;
1541 int prio = obj_load_order_prio(sec);
1542 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1543 if (obj_load_order_prio(*p) < prio)
1544 break;
1545 sec->load_next = *p;
1546 *p = sec;
1547}
1548
1549struct obj_section *obj_create_alloced_section(struct obj_file *f,
1550 const char *name,
1551 unsigned long align,
1552 unsigned long size)
1553{
1554 int newidx = f->header.e_shnum++;
1555 struct obj_section *sec;
1556
1557 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1558 f->sections[newidx] = sec = arch_new_section();
1559
1560 memset(sec, 0, sizeof(*sec));
1561 sec->header.sh_type = SHT_PROGBITS;
1562 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1563 sec->header.sh_size = size;
1564 sec->header.sh_addralign = align;
1565 sec->name = name;
1566 sec->idx = newidx;
1567 if (size)
1568 sec->contents = xmalloc(size);
1569
1570 obj_insert_section_load_order(f, sec);
1571
1572 return sec;
1573}
1574
1575struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1576 const char *name,
1577 unsigned long align,
1578 unsigned long size)
1579{
1580 int newidx = f->header.e_shnum++;
1581 struct obj_section *sec;
1582
1583 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1584 f->sections[newidx] = sec = arch_new_section();
1585
1586 memset(sec, 0, sizeof(*sec));
1587 sec->header.sh_type = SHT_PROGBITS;
1588 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1589 sec->header.sh_size = size;
1590 sec->header.sh_addralign = align;
1591 sec->name = name;
1592 sec->idx = newidx;
1593 if (size)
1594 sec->contents = xmalloc(size);
1595
1596 sec->load_next = f->load_order;
1597 f->load_order = sec;
1598 if (f->load_order_search_start == &f->load_order)
1599 f->load_order_search_start = &sec->load_next;
1600
1601 return sec;
1602}
1603
1604void *obj_extend_section(struct obj_section *sec, unsigned long more)
1605{
1606 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001607 if (more) {
1608 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1609 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001610 return sec->contents + oldsize;
1611}
1612
1613
1614
1615/* Conditionally add the symbols from the given symbol set to the
1616 new module. */
1617
1618static int
1619add_symbols_from(
1620 struct obj_file *f,
1621 int idx, struct new_module_symbol *syms, size_t nsyms)
1622{
1623 struct new_module_symbol *s;
1624 size_t i;
1625 int used = 0;
1626
1627 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1628
1629 /* Only add symbols that are already marked external. If we
1630 override locals we may cause problems for argument initialization.
1631 We will also create a false dependency on the module. */
1632 struct obj_symbol *sym;
1633
1634 sym = obj_find_symbol(f, (char *) s->name);
1635 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1636 sym = obj_add_symbol(f, (char *) s->name, -1,
1637 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1638 idx, s->value, 0);
1639 /* Did our symbol just get installed? If so, mark the
1640 module as "used". */
1641 if (sym->secidx == idx)
1642 used = 1;
1643 }
1644 }
1645
1646 return used;
1647}
1648
1649static void add_kernel_symbols(struct obj_file *f)
1650{
1651 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001652 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001653
1654 /* Add module symbols first. */
1655
1656 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1657 if (m->nsyms
1658 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1659 m->nsyms)) m->used = 1, ++nused;
1660
1661 n_ext_modules_used = nused;
1662
1663 /* And finally the symbols from the kernel proper. */
1664
1665 if (nksyms)
1666 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1667}
1668
1669static char *get_modinfo_value(struct obj_file *f, const char *key)
1670{
1671 struct obj_section *sec;
1672 char *p, *v, *n, *ep;
1673 size_t klen = strlen(key);
1674
1675 sec = obj_find_section(f, ".modinfo");
1676 if (sec == NULL)
1677 return NULL;
1678 p = sec->contents;
1679 ep = p + sec->header.sh_size;
1680 while (p < ep) {
1681 v = strchr(p, '=');
1682 n = strchr(p, '\0');
1683 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001684 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001685 return v + 1;
1686 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001687 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001688 return n;
1689 }
1690 p = n + 1;
1691 }
1692
1693 return NULL;
1694}
1695
1696
1697/*======================================================================*/
1698/* Functions relating to module loading in pre 2.1 kernels. */
1699
1700static int
1701old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1702{
1703 while (argc > 0) {
1704 char *p, *q;
1705 struct obj_symbol *sym;
1706 int *loc;
1707
1708 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001709 if ((q = strchr(p, '=')) == NULL) {
1710 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001711 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001712 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001713 *q++ = '\0';
1714
1715 sym = obj_find_symbol(f, p);
1716
1717 /* Also check that the parameter was not resolved from the kernel. */
1718 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001719 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001720 return 0;
1721 }
1722
1723 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1724
1725 /* Do C quoting if we begin with a ". */
1726 if (*q == '"') {
1727 char *r, *str;
1728
1729 str = alloca(strlen(q));
1730 for (r = str, q++; *q != '"'; ++q, ++r) {
1731 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001732 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001733 return 0;
1734 } else if (*q == '\\')
1735 switch (*++q) {
1736 case 'a':
1737 *r = '\a';
1738 break;
1739 case 'b':
1740 *r = '\b';
1741 break;
1742 case 'e':
1743 *r = '\033';
1744 break;
1745 case 'f':
1746 *r = '\f';
1747 break;
1748 case 'n':
1749 *r = '\n';
1750 break;
1751 case 'r':
1752 *r = '\r';
1753 break;
1754 case 't':
1755 *r = '\t';
1756 break;
1757
1758 case '0':
1759 case '1':
1760 case '2':
1761 case '3':
1762 case '4':
1763 case '5':
1764 case '6':
1765 case '7':
1766 {
1767 int c = *q - '0';
1768 if (q[1] >= '0' && q[1] <= '7') {
1769 c = (c * 8) + *++q - '0';
1770 if (q[1] >= '0' && q[1] <= '7')
1771 c = (c * 8) + *++q - '0';
1772 }
1773 *r = c;
1774 }
1775 break;
1776
1777 default:
1778 *r = *q;
1779 break;
1780 } else
1781 *r = *q;
1782 }
1783 *r = '\0';
1784 obj_string_patch(f, sym->secidx, sym->value, str);
1785 } else if (*q >= '0' && *q <= '9') {
1786 do
1787 *loc++ = strtoul(q, &q, 0);
1788 while (*q++ == ',');
1789 } else {
1790 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001791 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001792 char *r; /* To search for commas */
1793
1794 /* Break the string with comas */
1795 while ((r = strchr(q, ',')) != (char *) NULL) {
1796 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001797 obj_string_patch(f, sym->secidx, myloc - contents, q);
1798 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001799 q = r;
1800 }
1801
1802 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001803 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001804 }
1805
1806 argc--, argv++;
1807 }
1808
1809 return 1;
1810}
1811
1812#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1813static int old_is_module_checksummed(struct obj_file *f)
1814{
1815 return obj_find_symbol(f, "Using_Versions") != NULL;
1816}
1817/* Get the module's kernel version in the canonical integer form. */
1818
1819static int
1820old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1821{
1822 struct obj_symbol *sym;
1823 char *p, *q;
1824 int a, b, c;
1825
1826 sym = obj_find_symbol(f, "kernel_version");
1827 if (sym == NULL)
1828 return -1;
1829
1830 p = f->sections[sym->secidx]->contents + sym->value;
1831 strncpy(str, p, STRVERSIONLEN);
1832
1833 a = strtoul(p, &p, 10);
1834 if (*p != '.')
1835 return -1;
1836 b = strtoul(p + 1, &p, 10);
1837 if (*p != '.')
1838 return -1;
1839 c = strtoul(p + 1, &q, 10);
1840 if (p + 1 == q)
1841 return -1;
1842
1843 return a << 16 | b << 8 | c;
1844}
1845
1846#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1847
Eric Andersenf5d5e772001-01-24 23:34:48 +00001848#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001849
1850/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1851
Eric Andersen8c185f92000-09-22 00:38:07 +00001852static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001853{
1854 struct old_kernel_sym *ks, *k;
1855 struct new_module_symbol *s;
1856 struct external_module *mod;
1857 int nks, nms, nmod, i;
1858
1859 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001860 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001861 if (nks)
1862 perror_msg("get_kernel_syms: %s", m_name);
1863 else
1864 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001865 return 0;
1866 }
1867
1868 ks = k = xmalloc(nks * sizeof(*ks));
1869
1870 if (get_kernel_syms(ks) != nks) {
1871 perror("inconsistency with get_kernel_syms -- is someone else "
1872 "playing with modules?");
1873 free(ks);
1874 return 0;
1875 }
1876
1877 /* Collect the module information. */
1878
1879 mod = NULL;
1880 nmod = -1;
1881
1882 while (k->name[0] == '#' && k->name[1]) {
1883 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001884
1885 /* Find out how many symbols this module has. */
1886 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1887 continue;
1888 nms = k2 - k - 1;
1889
1890 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1891 mod[nmod].name = k->name + 1;
1892 mod[nmod].addr = k->value;
1893 mod[nmod].used = 0;
1894 mod[nmod].nsyms = nms;
1895 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1896
1897 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1898 s->name = (unsigned long) k->name;
1899 s->value = k->value;
1900 }
1901
1902 k = k2;
1903 }
1904
1905 ext_modules = mod;
1906 n_ext_modules = nmod + 1;
1907
1908 /* Now collect the symbols for the kernel proper. */
1909
1910 if (k->name[0] == '#')
1911 ++k;
1912
1913 nksyms = nms = nks - (k - ks);
1914 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1915
1916 for (i = 0; i < nms; ++i, ++s, ++k) {
1917 s->name = (unsigned long) k->name;
1918 s->value = k->value;
1919 }
1920
1921 return 1;
1922}
1923
1924/* Return the kernel symbol checksum version, or zero if not used. */
1925
1926static int old_is_kernel_checksummed(void)
1927{
1928 /* Using_Versions is the first symbol. */
1929 if (nksyms > 0
1930 && strcmp((char *) ksyms[0].name,
1931 "Using_Versions") == 0) return ksyms[0].value;
1932 else
1933 return 0;
1934}
1935
1936
1937static int old_create_mod_use_count(struct obj_file *f)
1938{
1939 struct obj_section *sec;
1940
1941 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1942 sizeof(long));
1943
1944 obj_add_symbol(f, "mod_use_count_", -1,
1945 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1946 sizeof(long));
1947
1948 return 1;
1949}
1950
1951static int
1952old_init_module(const char *m_name, struct obj_file *f,
1953 unsigned long m_size)
1954{
1955 char *image;
1956 struct old_mod_routines routines;
1957 struct old_symbol_table *symtab;
1958 int ret;
1959
1960 /* Create the symbol table */
1961 {
1962 int nsyms = 0, strsize = 0, total;
1963
1964 /* Size things first... */
1965 if (flag_export) {
1966 int i;
1967 for (i = 0; i < HASH_BUCKETS; ++i) {
1968 struct obj_symbol *sym;
1969 for (sym = f->symtab[i]; sym; sym = sym->next)
1970 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1971 && sym->secidx <= SHN_HIRESERVE)
1972 {
1973 sym->ksymidx = nsyms++;
1974 strsize += strlen(sym->name) + 1;
1975 }
1976 }
1977 }
1978
1979 total = (sizeof(struct old_symbol_table)
1980 + nsyms * sizeof(struct old_module_symbol)
1981 + n_ext_modules_used * sizeof(struct old_module_ref)
1982 + strsize);
1983 symtab = xmalloc(total);
1984 symtab->size = total;
1985 symtab->n_symbols = nsyms;
1986 symtab->n_refs = n_ext_modules_used;
1987
1988 if (flag_export && nsyms) {
1989 struct old_module_symbol *ksym;
1990 char *str;
1991 int i;
1992
1993 ksym = symtab->symbol;
1994 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1995 + n_ext_modules_used * sizeof(struct old_module_ref));
1996
1997 for (i = 0; i < HASH_BUCKETS; ++i) {
1998 struct obj_symbol *sym;
1999 for (sym = f->symtab[i]; sym; sym = sym->next)
2000 if (sym->ksymidx >= 0) {
2001 ksym->addr = obj_symbol_final_value(f, sym);
2002 ksym->name =
2003 (unsigned long) str - (unsigned long) symtab;
2004
Matt Kraai70a78552001-01-04 02:00:17 +00002005 strcpy(str, sym->name);
2006 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002007 ksym++;
2008 }
2009 }
2010 }
2011
2012 if (n_ext_modules_used) {
2013 struct old_module_ref *ref;
2014 int i;
2015
2016 ref = (struct old_module_ref *)
2017 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2018
2019 for (i = 0; i < n_ext_modules; ++i)
2020 if (ext_modules[i].used)
2021 ref++->module = ext_modules[i].addr;
2022 }
2023 }
2024
2025 /* Fill in routines. */
2026
2027 routines.init =
2028 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2029 routines.cleanup =
2030 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2031
2032 /* Whew! All of the initialization is complete. Collect the final
2033 module image and give it to the kernel. */
2034
2035 image = xmalloc(m_size);
2036 obj_create_image(f, image);
2037
2038 /* image holds the complete relocated module, accounting correctly for
2039 mod_use_count. However the old module kernel support assume that
2040 it is receiving something which does not contain mod_use_count. */
2041 ret = old_sys_init_module(m_name, image + sizeof(long),
2042 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2043 : 0), &routines, symtab);
2044 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002045 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002046
2047 free(image);
2048 free(symtab);
2049
2050 return ret == 0;
2051}
2052
2053#else
2054
2055#define old_create_mod_use_count(x) TRUE
2056#define old_init_module(x, y, z) TRUE
2057
Eric Andersenf5d5e772001-01-24 23:34:48 +00002058#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002059
2060
2061
2062/*======================================================================*/
2063/* Functions relating to module loading after 2.1.18. */
2064
2065static int
2066new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2067{
2068 while (argc > 0) {
2069 char *p, *q, *key;
2070 struct obj_symbol *sym;
2071 char *contents, *loc;
2072 int min, max, n;
2073
2074 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002075 if ((q = strchr(p, '=')) == NULL) {
2076 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002077 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002078 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002079
2080 key = alloca(q - p + 6);
2081 memcpy(key, "parm_", 5);
2082 memcpy(key + 5, p, q - p);
2083 key[q - p + 5] = 0;
2084
2085 p = get_modinfo_value(f, key);
2086 key += 5;
2087 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002088 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002089 return 0;
2090 }
2091
2092 sym = obj_find_symbol(f, key);
2093
2094 /* Also check that the parameter was not resolved from the kernel. */
2095 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002096 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002097 return 0;
2098 }
2099
2100 if (isdigit(*p)) {
2101 min = strtoul(p, &p, 10);
2102 if (*p == '-')
2103 max = strtoul(p + 1, &p, 10);
2104 else
2105 max = min;
2106 } else
2107 min = max = 1;
2108
2109 contents = f->sections[sym->secidx]->contents;
2110 loc = contents + sym->value;
2111 n = (*++q != '\0');
2112
2113 while (1) {
2114 if ((*p == 's') || (*p == 'c')) {
2115 char *str;
2116
2117 /* Do C quoting if we begin with a ", else slurp the lot. */
2118 if (*q == '"') {
2119 char *r;
2120
2121 str = alloca(strlen(q));
2122 for (r = str, q++; *q != '"'; ++q, ++r) {
2123 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002124 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002125 key);
2126 return 0;
2127 } else if (*q == '\\')
2128 switch (*++q) {
2129 case 'a':
2130 *r = '\a';
2131 break;
2132 case 'b':
2133 *r = '\b';
2134 break;
2135 case 'e':
2136 *r = '\033';
2137 break;
2138 case 'f':
2139 *r = '\f';
2140 break;
2141 case 'n':
2142 *r = '\n';
2143 break;
2144 case 'r':
2145 *r = '\r';
2146 break;
2147 case 't':
2148 *r = '\t';
2149 break;
2150
2151 case '0':
2152 case '1':
2153 case '2':
2154 case '3':
2155 case '4':
2156 case '5':
2157 case '6':
2158 case '7':
2159 {
2160 int c = *q - '0';
2161 if (q[1] >= '0' && q[1] <= '7') {
2162 c = (c * 8) + *++q - '0';
2163 if (q[1] >= '0' && q[1] <= '7')
2164 c = (c * 8) + *++q - '0';
2165 }
2166 *r = c;
2167 }
2168 break;
2169
2170 default:
2171 *r = *q;
2172 break;
2173 } else
2174 *r = *q;
2175 }
2176 *r = '\0';
2177 ++q;
2178 } else {
2179 char *r;
2180
2181 /* In this case, the string is not quoted. We will break
2182 it using the coma (like for ints). If the user wants to
2183 include comas in a string, he just has to quote it */
2184
2185 /* Search the next coma */
2186 r = strchr(q, ',');
2187
2188 /* Found ? */
2189 if (r != (char *) NULL) {
2190 /* Recopy the current field */
2191 str = alloca(r - q + 1);
2192 memcpy(str, q, r - q);
2193
2194 /* I don't know if it is usefull, as the previous case
2195 doesn't null terminate the string ??? */
2196 str[r - q] = '\0';
2197
2198 /* Keep next fields */
2199 q = r;
2200 } else {
2201 /* last string */
2202 str = q;
2203 q = "";
2204 }
2205 }
2206
2207 if (*p == 's') {
2208 /* Normal string */
2209 obj_string_patch(f, sym->secidx, loc - contents, str);
2210 loc += tgt_sizeof_char_p;
2211 } else {
2212 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002213 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002214
2215 /* Get the size of each member */
2216 /* Probably we should do that outside the loop ? */
2217 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002218 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002219 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002220 return 0;
2221 }
2222 charssize = strtoul(p + 1, (char **) NULL, 10);
2223
2224 /* Check length */
2225 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002226 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002227 charssize - 1);
2228 return 0;
2229 }
2230
2231 /* Copy to location */
2232 strcpy((char *) loc, str);
2233 loc += charssize;
2234 }
2235 } else {
2236 long v = strtoul(q, &q, 0);
2237 switch (*p) {
2238 case 'b':
2239 *loc++ = v;
2240 break;
2241 case 'h':
2242 *(short *) loc = v;
2243 loc += tgt_sizeof_short;
2244 break;
2245 case 'i':
2246 *(int *) loc = v;
2247 loc += tgt_sizeof_int;
2248 break;
2249 case 'l':
2250 *(long *) loc = v;
2251 loc += tgt_sizeof_long;
2252 break;
2253
2254 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002255 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002256 return 0;
2257 }
2258 }
2259
2260 retry_end_of_value:
2261 switch (*q) {
2262 case '\0':
2263 goto end_of_arg;
2264
2265 case ' ':
2266 case '\t':
2267 case '\n':
2268 case '\r':
2269 ++q;
2270 goto retry_end_of_value;
2271
2272 case ',':
2273 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002274 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002275 return 0;
2276 }
2277 ++q;
2278 break;
2279
2280 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002281 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002282 return 0;
2283 }
2284 }
2285
2286 end_of_arg:
2287 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002288 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002289 return 0;
2290 }
2291
2292 argc--, argv++;
2293 }
2294
2295 return 1;
2296}
2297
2298#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2299static int new_is_module_checksummed(struct obj_file *f)
2300{
2301 const char *p = get_modinfo_value(f, "using_checksums");
2302 if (p)
2303 return atoi(p);
2304 else
2305 return 0;
2306}
2307
2308/* Get the module's kernel version in the canonical integer form. */
2309
2310static int
2311new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2312{
2313 char *p, *q;
2314 int a, b, c;
2315
2316 p = get_modinfo_value(f, "kernel_version");
2317 if (p == NULL)
2318 return -1;
2319 strncpy(str, p, STRVERSIONLEN);
2320
2321 a = strtoul(p, &p, 10);
2322 if (*p != '.')
2323 return -1;
2324 b = strtoul(p + 1, &p, 10);
2325 if (*p != '.')
2326 return -1;
2327 c = strtoul(p + 1, &q, 10);
2328 if (p + 1 == q)
2329 return -1;
2330
2331 return a << 16 | b << 8 | c;
2332}
2333
2334#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2335
2336
Eric Andersenf5d5e772001-01-24 23:34:48 +00002337#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002338
2339/* Fetch the loaded modules, and all currently exported symbols. */
2340
2341static int new_get_kernel_symbols(void)
2342{
2343 char *module_names, *mn;
2344 struct external_module *modules, *m;
2345 struct new_module_symbol *syms, *s;
2346 size_t ret, bufsize, nmod, nsyms, i, j;
2347
2348 /* Collect the loaded modules. */
2349
2350 module_names = xmalloc(bufsize = 256);
2351 retry_modules_load:
2352 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002353 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002354 module_names = xrealloc(module_names, bufsize = ret);
2355 goto retry_modules_load;
2356 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002357 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002358 return 0;
2359 }
2360
2361 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002362
2363 /* Collect the modules' symbols. */
2364
Mark Whitley94fd4802001-03-12 23:08:34 +00002365 if (nmod){
2366 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2367 memset(modules, 0, nmod * sizeof(*modules));
2368 for (i = 0, mn = module_names, m = modules;
2369 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2370 struct new_module_info info;
2371
2372 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2373 if (errno == ENOENT) {
2374 /* The module was removed out from underneath us. */
2375 continue;
2376 }
2377 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002378 return 0;
2379 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002380
2381 syms = xmalloc(bufsize = 1024);
2382 retry_mod_sym_load:
2383 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2384 switch (errno) {
2385 case ENOSPC:
2386 syms = xrealloc(syms, bufsize = ret);
2387 goto retry_mod_sym_load;
2388 case ENOENT:
2389 /* The module was removed out from underneath us. */
2390 continue;
2391 default:
2392 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2393 return 0;
2394 }
2395 }
2396 nsyms = ret;
2397
2398 m->name = mn;
2399 m->addr = info.addr;
2400 m->nsyms = nsyms;
2401 m->syms = syms;
2402
2403 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2404 s->name += (unsigned long) syms;
2405 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 }
2407 }
2408
2409 /* Collect the kernel's symbols. */
2410
2411 syms = xmalloc(bufsize = 16 * 1024);
2412 retry_kern_sym_load:
2413 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002414 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002415 syms = xrealloc(syms, bufsize = ret);
2416 goto retry_kern_sym_load;
2417 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002418 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002419 return 0;
2420 }
2421 nksyms = nsyms = ret;
2422 ksyms = syms;
2423
2424 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2425 s->name += (unsigned long) syms;
2426 }
2427 return 1;
2428}
2429
2430
2431/* Return the kernel symbol checksum version, or zero if not used. */
2432
2433static int new_is_kernel_checksummed(void)
2434{
2435 struct new_module_symbol *s;
2436 size_t i;
2437
2438 /* Using_Versions is not the first symbol, but it should be in there. */
2439
2440 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2441 if (strcmp((char *) s->name, "Using_Versions") == 0)
2442 return s->value;
2443
2444 return 0;
2445}
2446
2447
2448static int new_create_this_module(struct obj_file *f, const char *m_name)
2449{
2450 struct obj_section *sec;
2451
2452 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2453 sizeof(struct new_module));
2454 memset(sec->contents, 0, sizeof(struct new_module));
2455
2456 obj_add_symbol(f, "__this_module", -1,
2457 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2458 sizeof(struct new_module));
2459
2460 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2461 m_name);
2462
2463 return 1;
2464}
2465
2466
2467static int new_create_module_ksymtab(struct obj_file *f)
2468{
2469 struct obj_section *sec;
2470 int i;
2471
2472 /* We must always add the module references. */
2473
2474 if (n_ext_modules_used) {
2475 struct new_module_ref *dep;
2476 struct obj_symbol *tm;
2477
2478 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2479 (sizeof(struct new_module_ref)
2480 * n_ext_modules_used));
2481 if (!sec)
2482 return 0;
2483
2484 tm = obj_find_symbol(f, "__this_module");
2485 dep = (struct new_module_ref *) sec->contents;
2486 for (i = 0; i < n_ext_modules; ++i)
2487 if (ext_modules[i].used) {
2488 dep->dep = ext_modules[i].addr;
2489 obj_symbol_patch(f, sec->idx,
2490 (char *) &dep->ref - sec->contents, tm);
2491 dep->next_ref = 0;
2492 ++dep;
2493 }
2494 }
2495
2496 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2497 size_t nsyms;
2498 int *loaded;
2499
2500 sec =
2501 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2502 0);
2503
2504 /* We don't want to export symbols residing in sections that
2505 aren't loaded. There are a number of these created so that
2506 we make sure certain module options don't appear twice. */
2507
2508 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2509 while (--i >= 0)
2510 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2511
2512 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2513 struct obj_symbol *sym;
2514 for (sym = f->symtab[i]; sym; sym = sym->next)
2515 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2516 && sym->secidx <= SHN_HIRESERVE
2517 && (sym->secidx >= SHN_LORESERVE
2518 || loaded[sym->secidx])) {
2519 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2520
2521 obj_symbol_patch(f, sec->idx, ofs, sym);
2522 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2523 sym->name);
2524
2525 nsyms++;
2526 }
2527 }
2528
2529 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2530 }
2531
2532 return 1;
2533}
2534
2535
2536static int
2537new_init_module(const char *m_name, struct obj_file *f,
2538 unsigned long m_size)
2539{
2540 struct new_module *module;
2541 struct obj_section *sec;
2542 void *image;
2543 int ret;
2544 tgt_long m_addr;
2545
2546 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002547 if (!sec || !sec->contents) {
2548 perror_msg_and_die("corrupt module %s?",m_name);
2549 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002550 module = (struct new_module *) sec->contents;
2551 m_addr = sec->header.sh_addr;
2552
2553 module->size_of_struct = sizeof(*module);
2554 module->size = m_size;
2555 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2556
2557 sec = obj_find_section(f, "__ksymtab");
2558 if (sec && sec->header.sh_size) {
2559 module->syms = sec->header.sh_addr;
2560 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2561 }
2562
2563 if (n_ext_modules_used) {
2564 sec = obj_find_section(f, ".kmodtab");
2565 module->deps = sec->header.sh_addr;
2566 module->ndeps = n_ext_modules_used;
2567 }
2568
2569 module->init =
2570 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2571 module->cleanup =
2572 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2573
2574 sec = obj_find_section(f, "__ex_table");
2575 if (sec) {
2576 module->ex_table_start = sec->header.sh_addr;
2577 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2578 }
2579
2580 sec = obj_find_section(f, ".text.init");
2581 if (sec) {
2582 module->runsize = sec->header.sh_addr - m_addr;
2583 }
2584 sec = obj_find_section(f, ".data.init");
2585 if (sec) {
2586 if (!module->runsize ||
2587 module->runsize > sec->header.sh_addr - m_addr)
2588 module->runsize = sec->header.sh_addr - m_addr;
2589 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002590 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2591 if (sec && sec->header.sh_size) {
2592 module->archdata_start = (void*)sec->header.sh_addr;
2593 module->archdata_end = module->archdata_start + sec->header.sh_size;
2594 }
2595 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2596 if (sec && sec->header.sh_size) {
2597 module->kallsyms_start = (void*)sec->header.sh_addr;
2598 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2599 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002600
2601 if (!arch_init_module(f, module))
2602 return 0;
2603
2604 /* Whew! All of the initialization is complete. Collect the final
2605 module image and give it to the kernel. */
2606
2607 image = xmalloc(m_size);
2608 obj_create_image(f, image);
2609
Eric Andersen64c8b172001-04-05 07:33:10 +00002610 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002611 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002612 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002613
2614 free(image);
2615
2616 return ret == 0;
2617}
2618
2619#else
2620
2621#define new_init_module(x, y, z) TRUE
2622#define new_create_this_module(x, y) 0
2623#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002624#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002625
Eric Andersenf5d5e772001-01-24 23:34:48 +00002626#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002627
2628
2629/*======================================================================*/
2630
2631int
2632obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2633 const char *string)
2634{
2635 struct obj_string_patch *p;
2636 struct obj_section *strsec;
2637 size_t len = strlen(string) + 1;
2638 char *loc;
2639
2640 p = xmalloc(sizeof(*p));
2641 p->next = f->string_patches;
2642 p->reloc_secidx = secidx;
2643 p->reloc_offset = offset;
2644 f->string_patches = p;
2645
2646 strsec = obj_find_section(f, ".kstrtab");
2647 if (strsec == NULL) {
2648 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2649 p->string_offset = 0;
2650 loc = strsec->contents;
2651 } else {
2652 p->string_offset = strsec->header.sh_size;
2653 loc = obj_extend_section(strsec, len);
2654 }
2655 memcpy(loc, string, len);
2656
2657 return 1;
2658}
2659
2660int
2661obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2662 struct obj_symbol *sym)
2663{
2664 struct obj_symbol_patch *p;
2665
2666 p = xmalloc(sizeof(*p));
2667 p->next = f->symbol_patches;
2668 p->reloc_secidx = secidx;
2669 p->reloc_offset = offset;
2670 p->sym = sym;
2671 f->symbol_patches = p;
2672
2673 return 1;
2674}
2675
2676int obj_check_undefineds(struct obj_file *f)
2677{
2678 unsigned long i;
2679 int ret = 1;
2680
2681 for (i = 0; i < HASH_BUCKETS; ++i) {
2682 struct obj_symbol *sym;
2683 for (sym = f->symtab[i]; sym; sym = sym->next)
2684 if (sym->secidx == SHN_UNDEF) {
2685 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2686 sym->secidx = SHN_ABS;
2687 sym->value = 0;
2688 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002689 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002690 ret = 0;
2691 }
2692 }
2693 }
2694
2695 return ret;
2696}
2697
2698void obj_allocate_commons(struct obj_file *f)
2699{
2700 struct common_entry {
2701 struct common_entry *next;
2702 struct obj_symbol *sym;
2703 } *common_head = NULL;
2704
2705 unsigned long i;
2706
2707 for (i = 0; i < HASH_BUCKETS; ++i) {
2708 struct obj_symbol *sym;
2709 for (sym = f->symtab[i]; sym; sym = sym->next)
2710 if (sym->secidx == SHN_COMMON) {
2711 /* Collect all COMMON symbols and sort them by size so as to
2712 minimize space wasted by alignment requirements. */
2713 {
2714 struct common_entry **p, *n;
2715 for (p = &common_head; *p; p = &(*p)->next)
2716 if (sym->size <= (*p)->sym->size)
2717 break;
2718
2719 n = alloca(sizeof(*n));
2720 n->next = *p;
2721 n->sym = sym;
2722 *p = n;
2723 }
2724 }
2725 }
2726
2727 for (i = 1; i < f->local_symtab_size; ++i) {
2728 struct obj_symbol *sym = f->local_symtab[i];
2729 if (sym && sym->secidx == SHN_COMMON) {
2730 struct common_entry **p, *n;
2731 for (p = &common_head; *p; p = &(*p)->next)
2732 if (sym == (*p)->sym)
2733 break;
2734 else if (sym->size < (*p)->sym->size) {
2735 n = alloca(sizeof(*n));
2736 n->next = *p;
2737 n->sym = sym;
2738 *p = n;
2739 break;
2740 }
2741 }
2742 }
2743
2744 if (common_head) {
2745 /* Find the bss section. */
2746 for (i = 0; i < f->header.e_shnum; ++i)
2747 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2748 break;
2749
2750 /* If for some reason there hadn't been one, create one. */
2751 if (i == f->header.e_shnum) {
2752 struct obj_section *sec;
2753
2754 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2755 f->sections[i] = sec = arch_new_section();
2756 f->header.e_shnum = i + 1;
2757
2758 memset(sec, 0, sizeof(*sec));
2759 sec->header.sh_type = SHT_PROGBITS;
2760 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2761 sec->name = ".bss";
2762 sec->idx = i;
2763 }
2764
2765 /* Allocate the COMMONS. */
2766 {
2767 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2768 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2769 struct common_entry *c;
2770
2771 for (c = common_head; c; c = c->next) {
2772 ElfW(Addr) align = c->sym->value;
2773
2774 if (align > max_align)
2775 max_align = align;
2776 if (bss_size & (align - 1))
2777 bss_size = (bss_size | (align - 1)) + 1;
2778
2779 c->sym->secidx = i;
2780 c->sym->value = bss_size;
2781
2782 bss_size += c->sym->size;
2783 }
2784
2785 f->sections[i]->header.sh_size = bss_size;
2786 f->sections[i]->header.sh_addralign = max_align;
2787 }
2788 }
2789
2790 /* For the sake of patch relocation and parameter initialization,
2791 allocate zeroed data for NOBITS sections now. Note that after
2792 this we cannot assume NOBITS are really empty. */
2793 for (i = 0; i < f->header.e_shnum; ++i) {
2794 struct obj_section *s = f->sections[i];
2795 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002796 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002797 s->contents = memset(xmalloc(s->header.sh_size),
2798 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002799 else
2800 s->contents = NULL;
2801
Eric Andersen9f16d612000-06-12 23:11:16 +00002802 s->header.sh_type = SHT_PROGBITS;
2803 }
2804 }
2805}
2806
2807unsigned long obj_load_size(struct obj_file *f)
2808{
2809 unsigned long dot = 0;
2810 struct obj_section *sec;
2811
2812 /* Finalize the positions of the sections relative to one another. */
2813
2814 for (sec = f->load_order; sec; sec = sec->load_next) {
2815 ElfW(Addr) align;
2816
2817 align = sec->header.sh_addralign;
2818 if (align && (dot & (align - 1)))
2819 dot = (dot | (align - 1)) + 1;
2820
2821 sec->header.sh_addr = dot;
2822 dot += sec->header.sh_size;
2823 }
2824
2825 return dot;
2826}
2827
2828int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2829{
2830 int i, n = f->header.e_shnum;
2831 int ret = 1;
2832
2833 /* Finalize the addresses of the sections. */
2834
2835 f->baseaddr = base;
2836 for (i = 0; i < n; ++i)
2837 f->sections[i]->header.sh_addr += base;
2838
2839 /* And iterate over all of the relocations. */
2840
2841 for (i = 0; i < n; ++i) {
2842 struct obj_section *relsec, *symsec, *targsec, *strsec;
2843 ElfW(RelM) * rel, *relend;
2844 ElfW(Sym) * symtab;
2845 const char *strtab;
2846
2847 relsec = f->sections[i];
2848 if (relsec->header.sh_type != SHT_RELM)
2849 continue;
2850
2851 symsec = f->sections[relsec->header.sh_link];
2852 targsec = f->sections[relsec->header.sh_info];
2853 strsec = f->sections[symsec->header.sh_link];
2854
2855 rel = (ElfW(RelM) *) relsec->contents;
2856 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2857 symtab = (ElfW(Sym) *) symsec->contents;
2858 strtab = (const char *) strsec->contents;
2859
2860 for (; rel < relend; ++rel) {
2861 ElfW(Addr) value = 0;
2862 struct obj_symbol *intsym = NULL;
2863 unsigned long symndx;
2864 ElfW(Sym) * extsym = 0;
2865 const char *errmsg;
2866
2867 /* Attempt to find a value to use for this relocation. */
2868
2869 symndx = ELFW(R_SYM) (rel->r_info);
2870 if (symndx) {
2871 /* Note we've already checked for undefined symbols. */
2872
2873 extsym = &symtab[symndx];
2874 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2875 /* Local symbols we look up in the local table to be sure
2876 we get the one that is really intended. */
2877 intsym = f->local_symtab[symndx];
2878 } else {
2879 /* Others we look up in the hash table. */
2880 const char *name;
2881 if (extsym->st_name)
2882 name = strtab + extsym->st_name;
2883 else
2884 name = f->sections[extsym->st_shndx]->name;
2885 intsym = obj_find_symbol(f, name);
2886 }
2887
2888 value = obj_symbol_final_value(f, intsym);
2889 intsym->referenced = 1;
2890 }
2891#if SHT_RELM == SHT_RELA
2892#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2893 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2894 if (!extsym || !extsym->st_name ||
2895 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2896#endif
2897 value += rel->r_addend;
2898#endif
2899
2900 /* Do it! */
2901 switch (arch_apply_relocation
2902 (f, targsec, symsec, intsym, rel, value)) {
2903 case obj_reloc_ok:
2904 break;
2905
2906 case obj_reloc_overflow:
2907 errmsg = "Relocation overflow";
2908 goto bad_reloc;
2909 case obj_reloc_dangerous:
2910 errmsg = "Dangerous relocation";
2911 goto bad_reloc;
2912 case obj_reloc_unhandled:
2913 errmsg = "Unhandled relocation";
2914 bad_reloc:
2915 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002916 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002917 (long) ELFW(R_TYPE) (rel->r_info),
2918 strtab + extsym->st_name);
2919 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002920 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002921 (long) ELFW(R_TYPE) (rel->r_info));
2922 }
2923 ret = 0;
2924 break;
2925 }
2926 }
2927 }
2928
2929 /* Finally, take care of the patches. */
2930
2931 if (f->string_patches) {
2932 struct obj_string_patch *p;
2933 struct obj_section *strsec;
2934 ElfW(Addr) strsec_base;
2935 strsec = obj_find_section(f, ".kstrtab");
2936 strsec_base = strsec->header.sh_addr;
2937
2938 for (p = f->string_patches; p; p = p->next) {
2939 struct obj_section *targsec = f->sections[p->reloc_secidx];
2940 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2941 = strsec_base + p->string_offset;
2942 }
2943 }
2944
2945 if (f->symbol_patches) {
2946 struct obj_symbol_patch *p;
2947
2948 for (p = f->symbol_patches; p; p = p->next) {
2949 struct obj_section *targsec = f->sections[p->reloc_secidx];
2950 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2951 = obj_symbol_final_value(f, p->sym);
2952 }
2953 }
2954
2955 return ret;
2956}
2957
2958int obj_create_image(struct obj_file *f, char *image)
2959{
2960 struct obj_section *sec;
2961 ElfW(Addr) base = f->baseaddr;
2962
2963 for (sec = f->load_order; sec; sec = sec->load_next) {
2964 char *secimg;
2965
Eric Andersen2bf658d2001-02-24 20:01:53 +00002966 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002967 continue;
2968
2969 secimg = image + (sec->header.sh_addr - base);
2970
2971 /* Note that we allocated data for NOBITS sections earlier. */
2972 memcpy(secimg, sec->contents, sec->header.sh_size);
2973 }
2974
2975 return 1;
2976}
2977
2978/*======================================================================*/
2979
Eric Andersen8ae319a2001-05-21 16:09:18 +00002980struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002981{
2982 struct obj_file *f;
2983 ElfW(Shdr) * section_headers;
2984 int shnum, i;
2985 char *shstrtab;
2986
2987 /* Read the file header. */
2988
2989 f = arch_new_file();
2990 memset(f, 0, sizeof(*f));
2991 f->symbol_cmp = strcmp;
2992 f->symbol_hash = obj_elf_hash;
2993 f->load_order_search_start = &f->load_order;
2994
2995 fseek(fp, 0, SEEK_SET);
2996 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002997 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002998 return NULL;
2999 }
3000
3001 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3002 || f->header.e_ident[EI_MAG1] != ELFMAG1
3003 || f->header.e_ident[EI_MAG2] != ELFMAG2
3004 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003005 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003006 return NULL;
3007 }
3008 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3009 || f->header.e_ident[EI_DATA] != ELFDATAM
3010 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3011 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003012 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003013 return NULL;
3014 }
3015 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003016 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003017 return NULL;
3018 }
3019
3020 /* Read the section headers. */
3021
3022 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003023 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003024 (unsigned long) f->header.e_shentsize,
3025 (unsigned long) sizeof(ElfW(Shdr)));
3026 return NULL;
3027 }
3028
3029 shnum = f->header.e_shnum;
3030 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3031 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3032
3033 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3034 fseek(fp, f->header.e_shoff, SEEK_SET);
3035 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003036 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003037 return NULL;
3038 }
3039
3040 /* Read the section data. */
3041
3042 for (i = 0; i < shnum; ++i) {
3043 struct obj_section *sec;
3044
3045 f->sections[i] = sec = arch_new_section();
3046 memset(sec, 0, sizeof(*sec));
3047
3048 sec->header = section_headers[i];
3049 sec->idx = i;
3050
Eric Andersen2bf658d2001-02-24 20:01:53 +00003051 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003052 case SHT_NULL:
3053 case SHT_NOTE:
3054 case SHT_NOBITS:
3055 /* ignore */
3056 break;
3057
3058 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003059#if LOADBITS
3060 if (!loadprogbits) {
3061 sec->contents = NULL;
3062 break;
3063 }
3064#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003065 case SHT_SYMTAB:
3066 case SHT_STRTAB:
3067 case SHT_RELM:
3068 if (sec->header.sh_size > 0) {
3069 sec->contents = xmalloc(sec->header.sh_size);
3070 fseek(fp, sec->header.sh_offset, SEEK_SET);
3071 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003072 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003073 return NULL;
3074 }
3075 } else {
3076 sec->contents = NULL;
3077 }
3078 break;
3079
3080#if SHT_RELM == SHT_REL
3081 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003082 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003083 return NULL;
3084#else
3085 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003086 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003087 return NULL;
3088#endif
3089
3090 default:
3091 if (sec->header.sh_type >= SHT_LOPROC) {
3092 /* Assume processor specific section types are debug
3093 info and can safely be ignored. If this is ever not
3094 the case (Hello MIPS?), don't put ifdefs here but
3095 create an arch_load_proc_section(). */
3096 break;
3097 }
3098
Matt Kraaidd19c692001-01-31 19:00:21 +00003099 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003100 (long) sec->header.sh_type);
3101 return NULL;
3102 }
3103 }
3104
3105 /* Do what sort of interpretation as needed by each section. */
3106
3107 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3108
3109 for (i = 0; i < shnum; ++i) {
3110 struct obj_section *sec = f->sections[i];
3111 sec->name = shstrtab + sec->header.sh_name;
3112 }
3113
3114 for (i = 0; i < shnum; ++i) {
3115 struct obj_section *sec = f->sections[i];
3116
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003117 /* .modinfo should be contents only but gcc has no attribute for that.
3118 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3119 */
3120 if (strcmp(sec->name, ".modinfo") == 0)
3121 sec->header.sh_flags &= ~SHF_ALLOC;
3122
Eric Andersen9f16d612000-06-12 23:11:16 +00003123 if (sec->header.sh_flags & SHF_ALLOC)
3124 obj_insert_section_load_order(f, sec);
3125
3126 switch (sec->header.sh_type) {
3127 case SHT_SYMTAB:
3128 {
3129 unsigned long nsym, j;
3130 char *strtab;
3131 ElfW(Sym) * sym;
3132
3133 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003134 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003135 (unsigned long) sec->header.sh_entsize,
3136 (unsigned long) sizeof(ElfW(Sym)));
3137 return NULL;
3138 }
3139
3140 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3141 strtab = f->sections[sec->header.sh_link]->contents;
3142 sym = (ElfW(Sym) *) sec->contents;
3143
3144 /* Allocate space for a table of local symbols. */
3145 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003146 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003147
3148 /* Insert all symbols into the hash table. */
3149 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3150 const char *name;
3151 if (sym->st_name)
3152 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003153 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003154 name = f->sections[sym->st_shndx]->name;
3155
3156 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3157 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003158 }
3159 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003160 break;
3161
3162 case SHT_RELM:
3163 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003164 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003165 (unsigned long) sec->header.sh_entsize,
3166 (unsigned long) sizeof(ElfW(RelM)));
3167 return NULL;
3168 }
3169 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003170 /* XXX Relocation code from modutils-2.3.19 is not here.
3171 * Why? That's about 20 lines of code from obj/obj_load.c,
3172 * which gets done in a second pass through the sections.
3173 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003174 }
3175 }
3176
3177 return f;
3178}
3179
Eric Andersen8ae319a2001-05-21 16:09:18 +00003180#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3181/*
3182 * load the unloaded sections directly into the memory allocated by
3183 * kernel for the module
3184 */
3185
3186int obj_load_progbits(FILE * fp, struct obj_file* f)
3187{
3188 char* imagebase = (char*) f->imagebase;
3189 ElfW(Addr) base = f->baseaddr;
3190 struct obj_section* sec;
3191
3192 for (sec = f->load_order; sec; sec = sec->load_next) {
3193
3194 /* section already loaded? */
3195 if (sec->contents != NULL)
3196 continue;
3197
3198 if (sec->header.sh_size == 0)
3199 continue;
3200
3201 sec->contents = imagebase + (sec->header.sh_addr - base);
3202 fseek(fp, sec->header.sh_offset, SEEK_SET);
3203 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3204 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3205 return 0;
3206 }
3207
3208 }
3209 return 1;
3210}
3211#endif
3212
Eric Andersen9f16d612000-06-12 23:11:16 +00003213static void hide_special_symbols(struct obj_file *f)
3214{
3215 static const char *const specials[] = {
3216 "cleanup_module",
3217 "init_module",
3218 "kernel_version",
3219 NULL
3220 };
3221
3222 struct obj_symbol *sym;
3223 const char *const *p;
3224
3225 for (p = specials; *p; ++p)
3226 if ((sym = obj_find_symbol(f, *p)) != NULL)
3227 sym->info =
3228 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3229}
3230
3231
3232
3233extern int insmod_main( int argc, char **argv)
3234{
Eric Andersena18aaf12001-01-24 19:07:09 +00003235 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003236 int k_crcs;
3237 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003238 int len;
3239 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003240 unsigned long m_size;
3241 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003242 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003243 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003244 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003245 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003246 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003247 int m_has_modinfo;
3248#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3249 int k_version;
3250 char k_strversion[STRVERSIONLEN];
3251 char m_strversion[STRVERSIONLEN];
3252 int m_version;
3253 int m_crcs;
3254#endif
3255
Erik Andersene49d5ec2000-02-08 19:58:47 +00003256 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003257 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003258 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003259 case 'f': /* force loading */
3260 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003261 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003262 case 'k': /* module loaded by kerneld, auto-cleanable */
3263 flag_autoclean = 1;
3264 break;
3265 case 'v': /* verbose output */
3266 flag_verbose = 1;
3267 break;
3268 case 'x': /* do not export externs */
3269 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003270 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003271 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003272 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003273 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003274 case 'L': /* Stub warning */
3275 /* This is needed for compatibility with modprobe.
3276 * In theory, this does locking, but we don't do
3277 * that. So be careful and plan your life around not
3278 * loading the same module 50 times concurrently. */
3279 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003280 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003281 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003282 }
Erik Andersend387d011999-12-21 02:55:11 +00003283 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003284
3285 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003286 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003287 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003288
Erik Andersene49d5ec2000-02-08 19:58:47 +00003289 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003290 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003291 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003292 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003293 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003294 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003295 len = strlen(tmp);
3296
3297 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3298 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003299 memcpy(m_fullName, tmp, len);
3300 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003301 if (*m_name == '\0') {
3302 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003303 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003304 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003305
Eric Andersen14d35432001-05-14 17:07:32 +00003306 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003307 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3308 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003309 struct utsname myuname;
3310
3311 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3312 * but do not error out yet if we fail to find it... */
3313 if (uname(&myuname) == 0) {
3314 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003315 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003316 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3317 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003318 /* Jump through hoops in case /lib/modules/`uname -r`
3319 * is a symlink. We do not want recursive_action to
3320 * follow symlinks, but we do want to follow the
3321 * /lib/modules/`uname -r` dir, So resolve it ourselves
3322 * if it is a link... */
3323 if (realpath (module_dir, real_module_dir) == NULL)
3324 strcpy(real_module_dir, module_dir);
3325 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003326 check_module_name_match, 0, m_fullName);
3327 }
3328
3329 /* Check if we have found anything yet */
3330 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003331 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003332 char module_dir[FILENAME_MAX];
3333 if (realpath (_PATH_MODULES, module_dir) == NULL)
3334 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003335 /* No module found under /lib/modules/`uname -r`, this
3336 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003337 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003338 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003339 {
Eric Andersen14d35432001-05-14 17:07:32 +00003340 if (m_filename[0] == '\0'
3341 || ((fp = fopen(m_filename, "r")) == NULL))
3342 {
3343 error_msg("%s: no module by that name found", m_fullName);
3344 return EXIT_FAILURE;
3345 }
3346 } else
3347 error_msg_and_die("%s: no module by that name found", m_fullName);
3348 }
3349 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003350 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003351
Eric Andersen14d35432001-05-14 17:07:32 +00003352 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003353
Eric Andersen8ae319a2001-05-21 16:09:18 +00003354 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003355 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003356
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 if (get_modinfo_value(f, "kernel_version") == NULL)
3358 m_has_modinfo = 0;
3359 else
3360 m_has_modinfo = 1;
3361
3362#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3363 /* Version correspondence? */
3364
3365 k_version = get_kernel_version(k_strversion);
3366 if (m_has_modinfo) {
3367 m_version = new_get_module_version(f, m_strversion);
3368 } else {
3369 m_version = old_get_module_version(f, m_strversion);
3370 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003371 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003372 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003373 goto out;
3374 }
3375 }
3376
3377 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3378 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003379 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003381 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003382 m_filename, m_strversion, k_strversion);
3383 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003384 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003385 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003386 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003387 m_filename, m_strversion, k_strversion);
3388 goto out;
3389 }
3390 }
3391 k_crcs = 0;
3392#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3393
3394 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3395
3396 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003397#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003398 if (!new_get_kernel_symbols())
3399 goto out;
3400 k_crcs = new_is_kernel_checksummed();
3401#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003402 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003403 goto out;
3404#endif
3405 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003406#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003407 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003408 goto out;
3409 k_crcs = old_is_kernel_checksummed();
3410#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003411 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003412 goto out;
3413#endif
3414 }
3415
3416#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3417 if (m_has_modinfo)
3418 m_crcs = new_is_module_checksummed(f);
3419 else
3420 m_crcs = old_is_module_checksummed(f);
3421
3422 if (m_crcs != k_crcs)
3423 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3424#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3425
Erik Andersene49d5ec2000-02-08 19:58:47 +00003426 /* Let the module know about the kernel symbols. */
3427 add_kernel_symbols(f);
3428
Eric Andersen9f16d612000-06-12 23:11:16 +00003429 /* Allocate common symbols, symbol tables, and string tables. */
3430
3431 if (k_new_syscalls
3432 ? !new_create_this_module(f, m_name)
3433 : !old_create_mod_use_count(f))
3434 {
3435 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003436 }
3437
Eric Andersen9f16d612000-06-12 23:11:16 +00003438 if (!obj_check_undefineds(f)) {
3439 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003440 }
3441 obj_allocate_commons(f);
3442
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003443 /* done with the module name, on to the optional var=value arguments */
3444 ++optind;
3445
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 if (optind < argc) {
3447 if (m_has_modinfo
3448 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3449 : !old_process_module_arguments(f, argc - optind, argv + optind))
3450 {
3451 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003452 }
3453 }
3454
Eric Andersen9f16d612000-06-12 23:11:16 +00003455 arch_create_got(f);
3456 hide_special_symbols(f);
3457
3458 if (k_new_syscalls)
3459 new_create_module_ksymtab(f);
3460
Erik Andersene49d5ec2000-02-08 19:58:47 +00003461 /* Find current size of the module */
3462 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003463
3464
Erik Andersene49d5ec2000-02-08 19:58:47 +00003465 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003466 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003467 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003468 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003469 goto out;
3470 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003471 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003472 m_size);
3473 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003474 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003475 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003476 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003477 }
Erik Andersend387d011999-12-21 02:55:11 +00003478
Eric Andersen8ae319a2001-05-21 16:09:18 +00003479#if !LOADBITS
3480 /*
3481 * the PROGBITS section was not loaded by the obj_load
3482 * now we can load them directly into the kernel memory
3483 */
3484 // f->imagebase = (char*) m_addr;
3485 f->imagebase = (ElfW(Addr)) m_addr;
3486 if (!obj_load_progbits(fp, f)) {
3487 delete_module(m_name);
3488 goto out;
3489 }
3490#endif
3491
Eric Andersen9f16d612000-06-12 23:11:16 +00003492 if (!obj_relocate(f, m_addr)) {
3493 delete_module(m_name);
3494 goto out;
3495 }
Erik Andersend387d011999-12-21 02:55:11 +00003496
Eric Andersen9f16d612000-06-12 23:11:16 +00003497 if (k_new_syscalls
3498 ? !new_init_module(m_name, f, m_size)
3499 : !old_init_module(m_name, f, m_size))
3500 {
3501 delete_module(m_name);
3502 goto out;
3503 }
3504
Matt Kraai3e856ce2000-12-01 02:55:13 +00003505 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003506
3507out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003508 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003509 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003510}