blob: 4ca28bb863068e12277b4ffd383c1966c7790fef [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 Andersen5a9d4412001-05-24 14:16:28 +0000133#ident "$Id: insmod.c,v 1.65 2001/05/24 14:16:28 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 Andersen5a9d4412001-05-24 14:16:28 +0000350#ident "$Id: insmod.c,v 1.65 2001/05/24 14:16:28 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
Eric Andersen8ae319a2001-05-21 16:09:18 +0000377#endif
378
379
380
Eric Andersenfe4208f2000-09-24 03:44:29 +0000381#if defined(__sh__)
382
383#define MATCH_MACHINE(x) (x == EM_SH)
384#define SHT_RELM SHT_RELA
385#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000386#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000387
Eric Andersen21adca72000-12-06 18:18:26 +0000388#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000389
Eric Andersen21adca72000-12-06 18:18:26 +0000390#define MATCH_MACHINE(x) (x == EM_ARM)
391#define SHT_RELM SHT_REL
392#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000393#define ELFDATAM ELFDATA2LSB
394
395#elif defined(__powerpc__)
396
397#define MATCH_MACHINE(x) (x == EM_PPC)
398#define SHT_RELM SHT_RELA
399#define Elf32_RelM Elf32_Rela
Eric Andersen5a9d4412001-05-24 14:16:28 +0000400#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000401
Eric Andersen2bf658d2001-02-24 20:01:53 +0000402#elif defined(__mips__)
403
Eric Andersen82bb8a22001-03-22 19:01:16 +0000404/* Account for ELF spec changes. */
405#ifndef EM_MIPS_RS3_LE
406#ifdef EM_MIPS_RS4_BE
407#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
408#else
409#define EM_MIPS_RS3_LE 10
410#endif
411#endif /* !EM_MIPS_RS3_LE */
412
Eric Andersen2bf658d2001-02-24 20:01:53 +0000413#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
414#define SHT_RELM SHT_REL
415#define Elf32_RelM Elf32_Rel
416#ifdef __MIPSEB__
417#define ELFDATAM ELFDATA2MSB
418#endif
419#ifdef __MIPSEL__
420#define ELFDATAM ELFDATA2LSB
421#endif
422
Eric Andersen21adca72000-12-06 18:18:26 +0000423#elif defined(__i386__)
424
425/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000426/* this is the previous behavior, but it does result in
427 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000428#ifndef EM_486
429#define MATCH_MACHINE(x) (x == EM_386)
430#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000431#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000432#endif
433
Eric Andersen9f16d612000-06-12 23:11:16 +0000434#define SHT_RELM SHT_REL
435#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000436#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000437
Eric Andersen8ae319a2001-05-21 16:09:18 +0000438#elif defined(__m68k__)
439
440#define MATCH_MACHINE(x) (x == EM_68K)
441#define SHT_RELM SHT_RELA
442#define Elf32_RelM Elf32_Rela
443
Eric Andersen21adca72000-12-06 18:18:26 +0000444#else
Eric Andersend5cad142001-01-26 02:23:57 +0000445#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000446#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000447
448#ifndef ElfW
449# if ELFCLASSM == ELFCLASS32
450# define ElfW(x) Elf32_ ## x
451# define ELFW(x) ELF32_ ## x
452# else
453# define ElfW(x) Elf64_ ## x
454# define ELFW(x) ELF64_ ## x
455# endif
456#endif
457
458/* For some reason this is missing from libc5. */
459#ifndef ELF32_ST_INFO
460# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
461#endif
462
463#ifndef ELF64_ST_INFO
464# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
465#endif
466
467struct obj_string_patch;
468struct obj_symbol_patch;
469
470struct obj_section
471{
472 ElfW(Shdr) header;
473 const char *name;
474 char *contents;
475 struct obj_section *load_next;
476 int idx;
477};
478
479struct obj_symbol
480{
481 struct obj_symbol *next; /* hash table link */
482 const char *name;
483 unsigned long value;
484 unsigned long size;
485 int secidx; /* the defining section index/module */
486 int info;
487 int ksymidx; /* for export to the kernel symtab */
488 int referenced; /* actually used in the link */
489};
490
491/* Hardcode the hash table size. We shouldn't be needing so many
492 symbols that we begin to degrade performance, and we get a big win
493 by giving the compiler a constant divisor. */
494
495#define HASH_BUCKETS 521
496
497struct obj_file
498{
499 ElfW(Ehdr) header;
500 ElfW(Addr) baseaddr;
501 struct obj_section **sections;
502 struct obj_section *load_order;
503 struct obj_section **load_order_search_start;
504 struct obj_string_patch *string_patches;
505 struct obj_symbol_patch *symbol_patches;
506 int (*symbol_cmp)(const char *, const char *);
507 unsigned long (*symbol_hash)(const char *);
508 unsigned long local_symtab_size;
509 struct obj_symbol **local_symtab;
510 struct obj_symbol *symtab[HASH_BUCKETS];
511};
512
513enum obj_reloc
514{
515 obj_reloc_ok,
516 obj_reloc_overflow,
517 obj_reloc_dangerous,
518 obj_reloc_unhandled
519};
520
521struct obj_string_patch
522{
523 struct obj_string_patch *next;
524 int reloc_secidx;
525 ElfW(Addr) reloc_offset;
526 ElfW(Addr) string_offset;
527};
528
529struct obj_symbol_patch
530{
531 struct obj_symbol_patch *next;
532 int reloc_secidx;
533 ElfW(Addr) reloc_offset;
534 struct obj_symbol *sym;
535};
536
537
538/* Generic object manipulation routines. */
539
540unsigned long obj_elf_hash(const char *);
541
542unsigned long obj_elf_hash_n(const char *, unsigned long len);
543
544struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
545 unsigned long symidx, int info, int secidx,
546 ElfW(Addr) value, unsigned long size);
547
548struct obj_symbol *obj_find_symbol (struct obj_file *f,
549 const char *name);
550
551ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
552 struct obj_symbol *sym);
553
554void obj_set_symbol_compare(struct obj_file *f,
555 int (*cmp)(const char *, const char *),
556 unsigned long (*hash)(const char *));
557
558struct obj_section *obj_find_section (struct obj_file *f,
559 const char *name);
560
561void obj_insert_section_load_order (struct obj_file *f,
562 struct obj_section *sec);
563
564struct obj_section *obj_create_alloced_section (struct obj_file *f,
565 const char *name,
566 unsigned long align,
567 unsigned long size);
568
569struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
570 const char *name,
571 unsigned long align,
572 unsigned long size);
573
574void *obj_extend_section (struct obj_section *sec, unsigned long more);
575
576int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
577 const char *string);
578
579int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
580 struct obj_symbol *sym);
581
582int obj_check_undefineds(struct obj_file *f);
583
584void obj_allocate_commons(struct obj_file *f);
585
586unsigned long obj_load_size (struct obj_file *f);
587
588int obj_relocate (struct obj_file *f, ElfW(Addr) base);
589
Eric Andersen8ae319a2001-05-21 16:09:18 +0000590struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000591
592int obj_create_image (struct obj_file *f, char *image);
593
594/* Architecture specific manipulation routines. */
595
596struct obj_file *arch_new_file (void);
597
598struct obj_section *arch_new_section (void);
599
600struct obj_symbol *arch_new_symbol (void);
601
602enum obj_reloc arch_apply_relocation (struct obj_file *f,
603 struct obj_section *targsec,
604 struct obj_section *symsec,
605 struct obj_symbol *sym,
606 ElfW(RelM) *rel, ElfW(Addr) value);
607
608int arch_create_got (struct obj_file *f);
609
610struct new_module;
611int arch_init_module (struct obj_file *f, struct new_module *);
612
613#endif /* obj.h */
614//----------------------------------------------------------------------------
615//--------end of modutils obj.h
616//----------------------------------------------------------------------------
617
618
619
620
Erik Andersen02104321999-12-17 18:57:34 +0000621
Erik Andersend387d011999-12-21 02:55:11 +0000622#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000623static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000624
Eric Andersen9f16d612000-06-12 23:11:16 +0000625/*======================================================================*/
626
627int flag_force_load = 0;
628int flag_autoclean = 0;
629int flag_verbose = 0;
630int flag_export = 1;
631
632
633/*======================================================================*/
634
Eric Andersenfe4208f2000-09-24 03:44:29 +0000635/* previously, these were named i386_* but since we could be
636 compiling for the sh, I've renamed them to the more general
637 arch_* These structures are the same between the x86 and SH,
638 and we can't support anything else right now anyway. In the
639 future maybe they should be #if defined'd */
640
Eric Andersen21adca72000-12-06 18:18:26 +0000641/* Done ;-) */
642
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000643
644
645#if defined(BB_USE_PLT_ENTRIES)
646struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000647{
648 int offset;
649 int allocated:1;
650 int inited:1; /* has been set up */
651};
652#endif
653
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000654#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000655struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 int offset;
657 unsigned offset_done:1;
658 unsigned reloc_done:1;
659};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000660#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen2bf658d2001-02-24 20:01:53 +0000662#if defined(__mips__)
663struct mips_hi16
664{
665 struct mips_hi16 *next;
666 Elf32_Addr *addr;
667 Elf32_Addr value;
668};
669#endif
670
Eric Andersenfe4208f2000-09-24 03:44:29 +0000671struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000672 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000673#if defined(BB_USE_PLT_ENTRIES)
674 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000675#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000676#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000677 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000678#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000679#if defined(__mips__)
680 struct mips_hi16 *mips_hi16_list;
681#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000682};
683
Eric Andersenfe4208f2000-09-24 03:44:29 +0000684struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000685 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000686#if defined(BB_USE_PLT_ENTRIES)
687 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000688#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000689#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000690 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000691#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000692};
693
694
Eric Andersen9f16d612000-06-12 23:11:16 +0000695struct external_module {
696 const char *name;
697 ElfW(Addr) addr;
698 int used;
699 size_t nsyms;
700 struct new_module_symbol *syms;
701};
702
703struct new_module_symbol *ksyms;
704size_t nksyms;
705
706struct external_module *ext_modules;
707int n_ext_modules;
708int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000709extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000710
Eric Andersen14d35432001-05-14 17:07:32 +0000711static char m_filename[FILENAME_MAX + 1];
712static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000713
Eric Andersenfe4208f2000-09-24 03:44:29 +0000714
Erik Andersen02104321999-12-17 18:57:34 +0000715
Eric Andersen9f16d612000-06-12 23:11:16 +0000716/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000717
Eric Andersen9f16d612000-06-12 23:11:16 +0000718
Eric Andersen14d35432001-05-14 17:07:32 +0000719static int check_module_name_match(const char *filename, struct stat *statbuf,
720 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000721{
Eric Andersen14d35432001-05-14 17:07:32 +0000722 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000723
Eric Andersen14d35432001-05-14 17:07:32 +0000724 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000725 return (FALSE);
726 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000727 char *tmp, *tmp1 = strdup(filename);
728 tmp = get_last_path_component(tmp1);
729 if (strcmp(tmp, fullname) == 0) {
730 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000731 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000732 safe_strncpy(m_filename, filename, sizeof(m_filename));
733 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000734 }
Eric Andersen14d35432001-05-14 17:07:32 +0000735 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000736 }
Eric Andersen14d35432001-05-14 17:07:32 +0000737 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000738}
739
Erik Andersen02104321999-12-17 18:57:34 +0000740
Eric Andersen9f16d612000-06-12 23:11:16 +0000741/*======================================================================*/
742
743struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000744{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000745 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000747
748#if defined(BB_USE_PLT_ENTRIES)
749 f->plt = NULL;
750#endif
751#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000752 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000753#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000754#if defined(__mips__)
755 f->mips_hi16_list = NULL;
756#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000757
Eric Andersen9f16d612000-06-12 23:11:16 +0000758 return &f->root;
759}
760
761struct obj_section *arch_new_section(void)
762{
763 return xmalloc(sizeof(struct obj_section));
764}
765
766struct obj_symbol *arch_new_symbol(void)
767{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000768 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000769 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000770
771#if defined(BB_USE_PLT_ENTRIES)
772 memset(&sym->pltent, 0, sizeof(sym->pltent));
773#endif
774#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000775 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000776#endif
777
Eric Andersen9f16d612000-06-12 23:11:16 +0000778 return &sym->root;
779}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000780
Eric Andersen9f16d612000-06-12 23:11:16 +0000781enum obj_reloc
782arch_apply_relocation(struct obj_file *f,
783 struct obj_section *targsec,
784 struct obj_section *symsec,
785 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000786 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000787{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000788 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000789#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000791#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000792
Eric Andersen21adca72000-12-06 18:18:26 +0000793 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
794 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000795#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000796 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000797#endif
798#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000799 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000800 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000801 unsigned long *ip;
802#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000803 enum obj_reloc ret = obj_reloc_ok;
804
805 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000806
807/* even though these constants seem to be the same for
808 the i386 and the sh, we "#if define" them for clarity
809 and in case that ever changes */
810#if defined(__sh__)
811 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000812#elif defined(__arm__)
813 case R_ARM_NONE:
814#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000815 case R_386_NONE:
Eric Andersen8ae319a2001-05-21 16:09:18 +0000816#elif defined(__m68k__)
817 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000818#elif defined(__powerpc__)
819 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000820#elif defined(__mips__)
821 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000822#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000823 break;
824
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825#if defined(__sh__)
826 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000827#elif defined(__arm__)
828 case R_ARM_ABS32:
829#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830 case R_386_32:
Eric Andersen8ae319a2001-05-21 16:09:18 +0000831#elif defined(__m68k__)
832 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833#elif defined(__powerpc__)
834 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000835#elif defined(__mips__)
836 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000837#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000838 *loc += v;
839 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000840#if defined(__m68k__)
841 case R_68K_8:
842 if (v > 0xff)
843 ret = obj_reloc_overflow;
844 *(char *)loc = v;
845 break;
846 case R_68K_16:
847 if (v > 0xffff)
848 ret = obj_reloc_overflow;
849 *(short *)loc = v;
850 break;
851#endif /* __m68k__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000852
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000853#if defined(__powerpc__)
854 case R_PPC_ADDR16_HA:
855 *(unsigned short *)loc = (v + 0x8000) >> 16;
856 break;
857
858 case R_PPC_ADDR16_HI:
859 *(unsigned short *)loc = v >> 16;
860 break;
861
862 case R_PPC_ADDR16_LO:
863 *(unsigned short *)loc = v;
864 break;
865#endif
866
Eric Andersen2bf658d2001-02-24 20:01:53 +0000867#if defined(__mips__)
868 case R_MIPS_26:
869 if (v % 4)
870 ret = obj_reloc_dangerous;
871 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
872 ret = obj_reloc_overflow;
873 *loc =
874 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
875 0x03ffffff);
876 break;
877
878 case R_MIPS_HI16:
879 {
880 struct mips_hi16 *n;
881
882 /* We cannot relocate this one now because we don't know the value
883 of the carry we need to add. Save the information, and let LO16
884 do the actual relocation. */
885 n = (struct mips_hi16 *) xmalloc(sizeof *n);
886 n->addr = loc;
887 n->value = v;
888 n->next = ifile->mips_hi16_list;
889 ifile->mips_hi16_list = n;
890 break;
891 }
892
893 case R_MIPS_LO16:
894 {
895 unsigned long insnlo = *loc;
896 Elf32_Addr val, vallo;
897
898 /* Sign extend the addend we extract from the lo insn. */
899 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
900
901 if (ifile->mips_hi16_list != NULL) {
902 struct mips_hi16 *l;
903
904 l = ifile->mips_hi16_list;
905 while (l != NULL) {
906 struct mips_hi16 *next;
907 unsigned long insn;
908
909 /* The value for the HI16 had best be the same. */
910 assert(v == l->value);
911
912 /* Do the HI16 relocation. Note that we actually don't
913 need to know anything about the LO16 itself, except where
914 to find the low 16 bits of the addend needed by the LO16. */
915 insn = *l->addr;
916 val =
917 ((insn & 0xffff) << 16) +
918 vallo;
919 val += v;
920
921 /* Account for the sign extension that will happen in the
922 low bits. */
923 val =
924 ((val >> 16) +
925 ((val & 0x8000) !=
926 0)) & 0xffff;
927
928 insn = (insn & ~0xffff) | val;
929 *l->addr = insn;
930
931 next = l->next;
932 free(l);
933 l = next;
934 }
935
936 ifile->mips_hi16_list = NULL;
937 }
938
939 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
940 val = v + vallo;
941 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
942 *loc = insnlo;
943 break;
944 }
945#endif
946
Eric Andersen21adca72000-12-06 18:18:26 +0000947#if defined(__arm__)
948#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000949 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000950 *loc += v - dot;
951 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000952#elif defined(__i386__)
953 case R_386_PLT32:
954 case R_386_PC32:
955 *loc += v - dot;
956 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000957#elif defined(__m68k__)
958 case R_68K_PC8:
959 v -= dot;
960 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
961 ret = obj_reloc_overflow;
962 *(char *)loc = v;
963 break;
964 case R_68K_PC16:
965 v -= dot;
966 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
967 ret = obj_reloc_overflow;
968 *(short *)loc = v;
969 break;
970 case R_68K_PC32:
971 *(int *)loc = v - dot;
972 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000973#elif defined(__powerpc__)
974 case R_PPC_REL32:
975 *loc = v - dot;
976 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000977#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000978
Eric Andersenfe4208f2000-09-24 03:44:29 +0000979#if defined(__sh__)
980 case R_SH_PLT32:
981 *loc = v - dot;
982 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000983#elif defined(__i386__)
984#endif
985
986#if defined(BB_USE_PLT_ENTRIES)
987
988#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000989 case R_ARM_PC24:
990 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000991#endif
992#if defined(__powerpc__)
993 case R_PPC_REL24:
994#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000995 /* find the plt entry and initialize it if necessary */
996 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000997
998 pe = (struct arch_plt_entry*) &isym->pltent;
999
Eric Andersen21adca72000-12-06 18:18:26 +00001000 if (! pe->inited) {
1001 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001002
1003 /* generate some machine code */
1004
1005#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001006 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1007 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001008#endif
1009#if defined(__powerpc__)
1010 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1011 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1012 ip[2] = 0x7d6903a6; /* mtctr r11 */
1013 ip[3] = 0x4e800420; /* bctr */
1014#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001015 pe->inited = 1;
1016 }
1017
1018 /* relative distance to target */
1019 v -= dot;
1020 /* if the target is too far away.... */
1021 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1022 /* go via the plt */
1023 v = plt + pe->offset - dot;
1024 }
1025 if (v & 3)
1026 ret = obj_reloc_dangerous;
1027
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001028 /* merge the offset into the instruction. */
1029#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001030 /* Convert to words. */
1031 v >>= 2;
1032
Eric Andersen21adca72000-12-06 18:18:26 +00001033 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001034#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001035#if defined(__powerpc__)
1036 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1037#endif
1038 break;
1039#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001040
Eric Andersen21adca72000-12-06 18:18:26 +00001041#if defined(__arm__)
1042#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001043 case R_SH_GLOB_DAT:
1044 case R_SH_JMP_SLOT:
1045 *loc = v;
1046 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001047#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001048 case R_386_GLOB_DAT:
1049 case R_386_JMP_SLOT:
1050 *loc = v;
1051 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001052#elif defined(__m68k__)
1053 case R_68K_GLOB_DAT:
1054 case R_68K_JMP_SLOT:
1055 *loc = v;
1056 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001058
Eric Andersen21adca72000-12-06 18:18:26 +00001059#if defined(__arm__)
1060#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001061 case R_SH_RELATIVE:
1062 *loc += f->baseaddr + rel->r_addend;
1063 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001064#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001065 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001066 *loc += f->baseaddr;
1067 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001068#elif defined(__m68k__)
1069 case R_68K_RELATIVE:
1070 *(int *)loc += f->baseaddr;
1071 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001072#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001073
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001074#if defined(BB_USE_GOT_ENTRIES)
1075
Eric Andersen8ae319a2001-05-21 16:09:18 +00001076#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001077#if defined(__sh__)
1078 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001079#elif defined(__arm__)
1080 case R_ARM_GOTPC:
1081#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001082 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001083#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001084 assert(got != 0);
1085#if defined(__sh__)
1086 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001087#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001088 *loc += got - dot;
1089#endif
1090 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001091#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001092
Eric Andersenfe4208f2000-09-24 03:44:29 +00001093#if defined(__sh__)
1094 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001095#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001096 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001097#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001098 case R_386_GOT32:
Eric Andersen8ae319a2001-05-21 16:09:18 +00001099#elif defined(__m68k__)
1100 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001101#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001102 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001103 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001104 if (!isym->gotent.reloc_done) {
1105 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001106 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001107 }
Eric Andersen21adca72000-12-06 18:18:26 +00001108 /* make the reloc with_respect_to_.got */
1109#if defined(__sh__)
1110 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001111#elif defined(__i386__) || defined(__arm__) || defined(__m68k__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001112 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001113#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001114 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001115
Eric Andersen21adca72000-12-06 18:18:26 +00001116 /* address relative to the got */
Eric Andersen8ae319a2001-05-21 16:09:18 +00001117#if !defined(__m68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001118#if defined(__sh__)
1119 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001120#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001121 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001122#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001123 case R_386_GOTOFF:
Eric Andersen8ae319a2001-05-21 16:09:18 +00001124#elif defined(__m68k__)
1125 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001126#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001127 assert(got != 0);
1128 *loc += v - got;
1129 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001130#endif // __m68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001131
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001132#endif /* BB_USE_GOT_ENTRIES */
1133
Eric Andersen9f16d612000-06-12 23:11:16 +00001134 default:
Eric Andersen21125542000-12-13 16:41:29 +00001135 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001136 ret = obj_reloc_unhandled;
1137 break;
1138 }
1139
1140 return ret;
1141}
1142
1143int arch_create_got(struct obj_file *f)
1144{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001145#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001146 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001147 int i;
1148#if defined(BB_USE_GOT_ENTRIES)
1149 int got_offset = 0, gotneeded = 0;
1150#endif
1151#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001152 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001153#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001154 struct obj_section *relsec, *symsec, *strsec;
1155 ElfW(RelM) *rel, *relend;
1156 ElfW(Sym) *symtab, *extsym;
1157 const char *strtab, *name;
1158 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001159
Eric Andersen21adca72000-12-06 18:18:26 +00001160 for (i = 0; i < f->header.e_shnum; ++i) {
1161 relsec = f->sections[i];
1162 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001163 continue;
1164
Eric Andersen21adca72000-12-06 18:18:26 +00001165 symsec = f->sections[relsec->header.sh_link];
1166 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001167
Eric Andersen21adca72000-12-06 18:18:26 +00001168 rel = (ElfW(RelM) *) relsec->contents;
1169 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1170 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001171 strtab = (const char *) strsec->contents;
1172
1173 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001174 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001175
1176 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001177#if defined(__arm__)
1178 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001179 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001180#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001181 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001182 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001183#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001184 case R_386_GOT32:
1185 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001186#elif defined(__m68k__)
1187 case R_68K_GOT32:
1188 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001189#endif
1190
1191#if defined(__powerpc__)
1192 case R_PPC_REL24:
1193 pltneeded = 1;
1194 break;
1195#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001196
1197#if defined(__arm__)
1198 case R_ARM_PC24:
1199 case R_ARM_PLT32:
1200 pltneeded = 1;
1201 break;
1202
1203 case R_ARM_GOTPC:
1204 case R_ARM_GOTOFF:
1205 gotneeded = 1;
1206 if (got_offset == 0)
1207 got_offset = 4;
1208#elif defined(__sh__)
1209 case R_SH_GOTPC:
1210 case R_SH_GOTOFF:
1211 gotneeded = 1;
1212#elif defined(__i386__)
1213 case R_386_GOTPC:
1214 case R_386_GOTOFF:
1215 gotneeded = 1;
1216#endif
1217
1218 default:
1219 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001220 }
1221
Eric Andersen21adca72000-12-06 18:18:26 +00001222 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001223 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001224 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001225 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001226 }
1227 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001228#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001229 if (!intsym->gotent.offset_done) {
1230 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001231 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001232 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001233 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001234#endif
1235#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001236 if (pltneeded && intsym->pltent.allocated == 0) {
1237 intsym->pltent.allocated = 1;
1238 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001239 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001240 intsym->pltent.inited = 0;
1241 pltneeded = 0;
1242 }
1243#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001244 }
1245 }
Eric Andersen21adca72000-12-06 18:18:26 +00001246
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001247#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001248 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001249 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001250
Eric Andersene76c3b02001-04-05 03:14:39 +00001251 if (myrelsec) {
1252 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001253 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001254 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001255 BB_GOT_ENTRY_SIZE,
1256 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001257 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001258 }
1259
Eric Andersene76c3b02001-04-05 03:14:39 +00001260 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001261 }
Eric Andersen21adca72000-12-06 18:18:26 +00001262#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001263
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001264#if defined(BB_USE_PLT_ENTRIES)
1265 if (plt_offset)
1266 ifile->plt = obj_create_alloced_section(f, ".plt",
1267 BB_PLT_ENTRY_SIZE,
1268 plt_offset);
1269#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001270#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001271 return 1;
1272}
1273
1274int arch_init_module(struct obj_file *f, struct new_module *mod)
1275{
1276 return 1;
1277}
1278
1279
1280/*======================================================================*/
1281
1282/* Standard ELF hash function. */
1283inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1284{
1285 unsigned long h = 0;
1286 unsigned long g;
1287 unsigned char ch;
1288
1289 while (n > 0) {
1290 ch = *name++;
1291 h = (h << 4) + ch;
1292 if ((g = (h & 0xf0000000)) != 0) {
1293 h ^= g >> 24;
1294 h &= ~g;
1295 }
1296 n--;
1297 }
1298 return h;
1299}
1300
1301unsigned long obj_elf_hash(const char *name)
1302{
1303 return obj_elf_hash_n(name, strlen(name));
1304}
1305
1306#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1307/* Get the kernel version in the canonical integer form. */
1308
1309static int get_kernel_version(char str[STRVERSIONLEN])
1310{
1311 struct utsname uts_info;
1312 char *p, *q;
1313 int a, b, c;
1314
1315 if (uname(&uts_info) < 0)
1316 return -1;
1317 strncpy(str, uts_info.release, STRVERSIONLEN);
1318 p = uts_info.release;
1319
1320 a = strtoul(p, &p, 10);
1321 if (*p != '.')
1322 return -1;
1323 b = strtoul(p + 1, &p, 10);
1324 if (*p != '.')
1325 return -1;
1326 c = strtoul(p + 1, &q, 10);
1327 if (p + 1 == q)
1328 return -1;
1329
1330 return a << 16 | b << 8 | c;
1331}
1332
1333/* String comparison for non-co-versioned kernel and module. */
1334
1335static int ncv_strcmp(const char *a, const char *b)
1336{
1337 size_t alen = strlen(a), blen = strlen(b);
1338
1339 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1340 return strncmp(a, b, alen);
1341 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1342 return strncmp(a, b, blen);
1343 else
1344 return strcmp(a, b);
1345}
1346
1347/* String hashing for non-co-versioned kernel and module. Here
1348 we are simply forced to drop the crc from the hash. */
1349
1350static unsigned long ncv_symbol_hash(const char *str)
1351{
1352 size_t len = strlen(str);
1353 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1354 len -= 10;
1355 return obj_elf_hash_n(str, len);
1356}
1357
1358void
1359obj_set_symbol_compare(struct obj_file *f,
1360 int (*cmp) (const char *, const char *),
1361 unsigned long (*hash) (const char *))
1362{
1363 if (cmp)
1364 f->symbol_cmp = cmp;
1365 if (hash) {
1366 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1367 int i;
1368
1369 f->symbol_hash = hash;
1370
1371 memcpy(tmptab, f->symtab, sizeof(tmptab));
1372 memset(f->symtab, 0, sizeof(f->symtab));
1373
1374 for (i = 0; i < HASH_BUCKETS; ++i)
1375 for (sym = tmptab[i]; sym; sym = next) {
1376 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1377 next = sym->next;
1378 sym->next = f->symtab[h];
1379 f->symtab[h] = sym;
1380 }
1381 }
1382}
1383
1384#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1385
1386
1387struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1388 unsigned long symidx, int info,
1389 int secidx, ElfW(Addr) value,
1390 unsigned long size)
1391{
1392 struct obj_symbol *sym;
1393 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1394 int n_type = ELFW(ST_TYPE) (info);
1395 int n_binding = ELFW(ST_BIND) (info);
1396
1397 for (sym = f->symtab[hash]; sym; sym = sym->next)
1398 if (f->symbol_cmp(sym->name, name) == 0) {
1399 int o_secidx = sym->secidx;
1400 int o_info = sym->info;
1401 int o_type = ELFW(ST_TYPE) (o_info);
1402 int o_binding = ELFW(ST_BIND) (o_info);
1403
1404 /* A redefinition! Is it legal? */
1405
1406 if (secidx == SHN_UNDEF)
1407 return sym;
1408 else if (o_secidx == SHN_UNDEF)
1409 goto found;
1410 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1411 /* Cope with local and global symbols of the same name
1412 in the same object file, as might have been created
1413 by ld -r. The only reason locals are now seen at this
1414 level at all is so that we can do semi-sensible things
1415 with parameters. */
1416
1417 struct obj_symbol *nsym, **p;
1418
1419 nsym = arch_new_symbol();
1420 nsym->next = sym->next;
1421 nsym->ksymidx = -1;
1422
1423 /* Excise the old (local) symbol from the hash chain. */
1424 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1425 continue;
1426 *p = sym = nsym;
1427 goto found;
1428 } else if (n_binding == STB_LOCAL) {
1429 /* Another symbol of the same name has already been defined.
1430 Just add this to the local table. */
1431 sym = arch_new_symbol();
1432 sym->next = NULL;
1433 sym->ksymidx = -1;
1434 f->local_symtab[symidx] = sym;
1435 goto found;
1436 } else if (n_binding == STB_WEAK)
1437 return sym;
1438 else if (o_binding == STB_WEAK)
1439 goto found;
1440 /* Don't unify COMMON symbols with object types the programmer
1441 doesn't expect. */
1442 else if (secidx == SHN_COMMON
1443 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1444 return sym;
1445 else if (o_secidx == SHN_COMMON
1446 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1447 goto found;
1448 else {
1449 /* Don't report an error if the symbol is coming from
1450 the kernel or some external module. */
1451 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001452 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001453 return sym;
1454 }
1455 }
1456
1457 /* Completely new symbol. */
1458 sym = arch_new_symbol();
1459 sym->next = f->symtab[hash];
1460 f->symtab[hash] = sym;
1461 sym->ksymidx = -1;
1462
1463 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1464 f->local_symtab[symidx] = sym;
1465
1466 found:
1467 sym->name = name;
1468 sym->value = value;
1469 sym->size = size;
1470 sym->secidx = secidx;
1471 sym->info = info;
1472
1473 return sym;
1474}
1475
1476struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1477{
1478 struct obj_symbol *sym;
1479 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1480
1481 for (sym = f->symtab[hash]; sym; sym = sym->next)
1482 if (f->symbol_cmp(sym->name, name) == 0)
1483 return sym;
1484
1485 return NULL;
1486}
1487
1488ElfW(Addr)
1489 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1490{
1491 if (sym) {
1492 if (sym->secidx >= SHN_LORESERVE)
1493 return sym->value;
1494
1495 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1496 } else {
1497 /* As a special case, a NULL sym has value zero. */
1498 return 0;
1499 }
1500}
1501
1502struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1503{
1504 int i, n = f->header.e_shnum;
1505
1506 for (i = 0; i < n; ++i)
1507 if (strcmp(f->sections[i]->name, name) == 0)
1508 return f->sections[i];
1509
1510 return NULL;
1511}
1512
1513static int obj_load_order_prio(struct obj_section *a)
1514{
1515 unsigned long af, ac;
1516
1517 af = a->header.sh_flags;
1518
1519 ac = 0;
1520 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1521 strcmp(a->name + 5, ".init"))
1522 ac |= 32;
1523 if (af & SHF_ALLOC)
1524 ac |= 16;
1525 if (!(af & SHF_WRITE))
1526 ac |= 8;
1527 if (af & SHF_EXECINSTR)
1528 ac |= 4;
1529 if (a->header.sh_type != SHT_NOBITS)
1530 ac |= 2;
1531
1532 return ac;
1533}
1534
1535void
1536obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1537{
1538 struct obj_section **p;
1539 int prio = obj_load_order_prio(sec);
1540 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1541 if (obj_load_order_prio(*p) < prio)
1542 break;
1543 sec->load_next = *p;
1544 *p = sec;
1545}
1546
1547struct obj_section *obj_create_alloced_section(struct obj_file *f,
1548 const char *name,
1549 unsigned long align,
1550 unsigned long size)
1551{
1552 int newidx = f->header.e_shnum++;
1553 struct obj_section *sec;
1554
1555 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1556 f->sections[newidx] = sec = arch_new_section();
1557
1558 memset(sec, 0, sizeof(*sec));
1559 sec->header.sh_type = SHT_PROGBITS;
1560 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1561 sec->header.sh_size = size;
1562 sec->header.sh_addralign = align;
1563 sec->name = name;
1564 sec->idx = newidx;
1565 if (size)
1566 sec->contents = xmalloc(size);
1567
1568 obj_insert_section_load_order(f, sec);
1569
1570 return sec;
1571}
1572
1573struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1574 const char *name,
1575 unsigned long align,
1576 unsigned long size)
1577{
1578 int newidx = f->header.e_shnum++;
1579 struct obj_section *sec;
1580
1581 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1582 f->sections[newidx] = sec = arch_new_section();
1583
1584 memset(sec, 0, sizeof(*sec));
1585 sec->header.sh_type = SHT_PROGBITS;
1586 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1587 sec->header.sh_size = size;
1588 sec->header.sh_addralign = align;
1589 sec->name = name;
1590 sec->idx = newidx;
1591 if (size)
1592 sec->contents = xmalloc(size);
1593
1594 sec->load_next = f->load_order;
1595 f->load_order = sec;
1596 if (f->load_order_search_start == &f->load_order)
1597 f->load_order_search_start = &sec->load_next;
1598
1599 return sec;
1600}
1601
1602void *obj_extend_section(struct obj_section *sec, unsigned long more)
1603{
1604 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001605 if (more) {
1606 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1607 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001608 return sec->contents + oldsize;
1609}
1610
1611
1612
1613/* Conditionally add the symbols from the given symbol set to the
1614 new module. */
1615
1616static int
1617add_symbols_from(
1618 struct obj_file *f,
1619 int idx, struct new_module_symbol *syms, size_t nsyms)
1620{
1621 struct new_module_symbol *s;
1622 size_t i;
1623 int used = 0;
1624
1625 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1626
1627 /* Only add symbols that are already marked external. If we
1628 override locals we may cause problems for argument initialization.
1629 We will also create a false dependency on the module. */
1630 struct obj_symbol *sym;
1631
1632 sym = obj_find_symbol(f, (char *) s->name);
1633 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1634 sym = obj_add_symbol(f, (char *) s->name, -1,
1635 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1636 idx, s->value, 0);
1637 /* Did our symbol just get installed? If so, mark the
1638 module as "used". */
1639 if (sym->secidx == idx)
1640 used = 1;
1641 }
1642 }
1643
1644 return used;
1645}
1646
1647static void add_kernel_symbols(struct obj_file *f)
1648{
1649 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001650 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001651
1652 /* Add module symbols first. */
1653
1654 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1655 if (m->nsyms
1656 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1657 m->nsyms)) m->used = 1, ++nused;
1658
1659 n_ext_modules_used = nused;
1660
1661 /* And finally the symbols from the kernel proper. */
1662
1663 if (nksyms)
1664 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1665}
1666
1667static char *get_modinfo_value(struct obj_file *f, const char *key)
1668{
1669 struct obj_section *sec;
1670 char *p, *v, *n, *ep;
1671 size_t klen = strlen(key);
1672
1673 sec = obj_find_section(f, ".modinfo");
1674 if (sec == NULL)
1675 return NULL;
1676 p = sec->contents;
1677 ep = p + sec->header.sh_size;
1678 while (p < ep) {
1679 v = strchr(p, '=');
1680 n = strchr(p, '\0');
1681 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001682 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001683 return v + 1;
1684 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001685 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001686 return n;
1687 }
1688 p = n + 1;
1689 }
1690
1691 return NULL;
1692}
1693
1694
1695/*======================================================================*/
1696/* Functions relating to module loading in pre 2.1 kernels. */
1697
1698static int
1699old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1700{
1701 while (argc > 0) {
1702 char *p, *q;
1703 struct obj_symbol *sym;
1704 int *loc;
1705
1706 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001707 if ((q = strchr(p, '=')) == NULL) {
1708 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001709 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001710 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001711 *q++ = '\0';
1712
1713 sym = obj_find_symbol(f, p);
1714
1715 /* Also check that the parameter was not resolved from the kernel. */
1716 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001717 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001718 return 0;
1719 }
1720
1721 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1722
1723 /* Do C quoting if we begin with a ". */
1724 if (*q == '"') {
1725 char *r, *str;
1726
1727 str = alloca(strlen(q));
1728 for (r = str, q++; *q != '"'; ++q, ++r) {
1729 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001730 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001731 return 0;
1732 } else if (*q == '\\')
1733 switch (*++q) {
1734 case 'a':
1735 *r = '\a';
1736 break;
1737 case 'b':
1738 *r = '\b';
1739 break;
1740 case 'e':
1741 *r = '\033';
1742 break;
1743 case 'f':
1744 *r = '\f';
1745 break;
1746 case 'n':
1747 *r = '\n';
1748 break;
1749 case 'r':
1750 *r = '\r';
1751 break;
1752 case 't':
1753 *r = '\t';
1754 break;
1755
1756 case '0':
1757 case '1':
1758 case '2':
1759 case '3':
1760 case '4':
1761 case '5':
1762 case '6':
1763 case '7':
1764 {
1765 int c = *q - '0';
1766 if (q[1] >= '0' && q[1] <= '7') {
1767 c = (c * 8) + *++q - '0';
1768 if (q[1] >= '0' && q[1] <= '7')
1769 c = (c * 8) + *++q - '0';
1770 }
1771 *r = c;
1772 }
1773 break;
1774
1775 default:
1776 *r = *q;
1777 break;
1778 } else
1779 *r = *q;
1780 }
1781 *r = '\0';
1782 obj_string_patch(f, sym->secidx, sym->value, str);
1783 } else if (*q >= '0' && *q <= '9') {
1784 do
1785 *loc++ = strtoul(q, &q, 0);
1786 while (*q++ == ',');
1787 } else {
1788 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001789 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001790 char *r; /* To search for commas */
1791
1792 /* Break the string with comas */
1793 while ((r = strchr(q, ',')) != (char *) NULL) {
1794 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001795 obj_string_patch(f, sym->secidx, myloc - contents, q);
1796 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001797 q = r;
1798 }
1799
1800 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001801 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001802 }
1803
1804 argc--, argv++;
1805 }
1806
1807 return 1;
1808}
1809
1810#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1811static int old_is_module_checksummed(struct obj_file *f)
1812{
1813 return obj_find_symbol(f, "Using_Versions") != NULL;
1814}
1815/* Get the module's kernel version in the canonical integer form. */
1816
1817static int
1818old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1819{
1820 struct obj_symbol *sym;
1821 char *p, *q;
1822 int a, b, c;
1823
1824 sym = obj_find_symbol(f, "kernel_version");
1825 if (sym == NULL)
1826 return -1;
1827
1828 p = f->sections[sym->secidx]->contents + sym->value;
1829 strncpy(str, p, STRVERSIONLEN);
1830
1831 a = strtoul(p, &p, 10);
1832 if (*p != '.')
1833 return -1;
1834 b = strtoul(p + 1, &p, 10);
1835 if (*p != '.')
1836 return -1;
1837 c = strtoul(p + 1, &q, 10);
1838 if (p + 1 == q)
1839 return -1;
1840
1841 return a << 16 | b << 8 | c;
1842}
1843
1844#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1845
Eric Andersenf5d5e772001-01-24 23:34:48 +00001846#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001847
1848/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1849
Eric Andersen8c185f92000-09-22 00:38:07 +00001850static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001851{
1852 struct old_kernel_sym *ks, *k;
1853 struct new_module_symbol *s;
1854 struct external_module *mod;
1855 int nks, nms, nmod, i;
1856
1857 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001858 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001859 if (nks)
1860 perror_msg("get_kernel_syms: %s", m_name);
1861 else
1862 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001863 return 0;
1864 }
1865
1866 ks = k = xmalloc(nks * sizeof(*ks));
1867
1868 if (get_kernel_syms(ks) != nks) {
1869 perror("inconsistency with get_kernel_syms -- is someone else "
1870 "playing with modules?");
1871 free(ks);
1872 return 0;
1873 }
1874
1875 /* Collect the module information. */
1876
1877 mod = NULL;
1878 nmod = -1;
1879
1880 while (k->name[0] == '#' && k->name[1]) {
1881 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001882
1883 /* Find out how many symbols this module has. */
1884 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1885 continue;
1886 nms = k2 - k - 1;
1887
1888 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1889 mod[nmod].name = k->name + 1;
1890 mod[nmod].addr = k->value;
1891 mod[nmod].used = 0;
1892 mod[nmod].nsyms = nms;
1893 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1894
1895 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1896 s->name = (unsigned long) k->name;
1897 s->value = k->value;
1898 }
1899
1900 k = k2;
1901 }
1902
1903 ext_modules = mod;
1904 n_ext_modules = nmod + 1;
1905
1906 /* Now collect the symbols for the kernel proper. */
1907
1908 if (k->name[0] == '#')
1909 ++k;
1910
1911 nksyms = nms = nks - (k - ks);
1912 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1913
1914 for (i = 0; i < nms; ++i, ++s, ++k) {
1915 s->name = (unsigned long) k->name;
1916 s->value = k->value;
1917 }
1918
1919 return 1;
1920}
1921
1922/* Return the kernel symbol checksum version, or zero if not used. */
1923
1924static int old_is_kernel_checksummed(void)
1925{
1926 /* Using_Versions is the first symbol. */
1927 if (nksyms > 0
1928 && strcmp((char *) ksyms[0].name,
1929 "Using_Versions") == 0) return ksyms[0].value;
1930 else
1931 return 0;
1932}
1933
1934
1935static int old_create_mod_use_count(struct obj_file *f)
1936{
1937 struct obj_section *sec;
1938
1939 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1940 sizeof(long));
1941
1942 obj_add_symbol(f, "mod_use_count_", -1,
1943 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1944 sizeof(long));
1945
1946 return 1;
1947}
1948
1949static int
1950old_init_module(const char *m_name, struct obj_file *f,
1951 unsigned long m_size)
1952{
1953 char *image;
1954 struct old_mod_routines routines;
1955 struct old_symbol_table *symtab;
1956 int ret;
1957
1958 /* Create the symbol table */
1959 {
1960 int nsyms = 0, strsize = 0, total;
1961
1962 /* Size things first... */
1963 if (flag_export) {
1964 int i;
1965 for (i = 0; i < HASH_BUCKETS; ++i) {
1966 struct obj_symbol *sym;
1967 for (sym = f->symtab[i]; sym; sym = sym->next)
1968 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1969 && sym->secidx <= SHN_HIRESERVE)
1970 {
1971 sym->ksymidx = nsyms++;
1972 strsize += strlen(sym->name) + 1;
1973 }
1974 }
1975 }
1976
1977 total = (sizeof(struct old_symbol_table)
1978 + nsyms * sizeof(struct old_module_symbol)
1979 + n_ext_modules_used * sizeof(struct old_module_ref)
1980 + strsize);
1981 symtab = xmalloc(total);
1982 symtab->size = total;
1983 symtab->n_symbols = nsyms;
1984 symtab->n_refs = n_ext_modules_used;
1985
1986 if (flag_export && nsyms) {
1987 struct old_module_symbol *ksym;
1988 char *str;
1989 int i;
1990
1991 ksym = symtab->symbol;
1992 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1993 + n_ext_modules_used * sizeof(struct old_module_ref));
1994
1995 for (i = 0; i < HASH_BUCKETS; ++i) {
1996 struct obj_symbol *sym;
1997 for (sym = f->symtab[i]; sym; sym = sym->next)
1998 if (sym->ksymidx >= 0) {
1999 ksym->addr = obj_symbol_final_value(f, sym);
2000 ksym->name =
2001 (unsigned long) str - (unsigned long) symtab;
2002
Matt Kraai70a78552001-01-04 02:00:17 +00002003 strcpy(str, sym->name);
2004 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002005 ksym++;
2006 }
2007 }
2008 }
2009
2010 if (n_ext_modules_used) {
2011 struct old_module_ref *ref;
2012 int i;
2013
2014 ref = (struct old_module_ref *)
2015 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2016
2017 for (i = 0; i < n_ext_modules; ++i)
2018 if (ext_modules[i].used)
2019 ref++->module = ext_modules[i].addr;
2020 }
2021 }
2022
2023 /* Fill in routines. */
2024
2025 routines.init =
2026 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2027 routines.cleanup =
2028 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2029
2030 /* Whew! All of the initialization is complete. Collect the final
2031 module image and give it to the kernel. */
2032
2033 image = xmalloc(m_size);
2034 obj_create_image(f, image);
2035
2036 /* image holds the complete relocated module, accounting correctly for
2037 mod_use_count. However the old module kernel support assume that
2038 it is receiving something which does not contain mod_use_count. */
2039 ret = old_sys_init_module(m_name, image + sizeof(long),
2040 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2041 : 0), &routines, symtab);
2042 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002043 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002044
2045 free(image);
2046 free(symtab);
2047
2048 return ret == 0;
2049}
2050
2051#else
2052
2053#define old_create_mod_use_count(x) TRUE
2054#define old_init_module(x, y, z) TRUE
2055
Eric Andersenf5d5e772001-01-24 23:34:48 +00002056#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002057
2058
2059
2060/*======================================================================*/
2061/* Functions relating to module loading after 2.1.18. */
2062
2063static int
2064new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2065{
2066 while (argc > 0) {
2067 char *p, *q, *key;
2068 struct obj_symbol *sym;
2069 char *contents, *loc;
2070 int min, max, n;
2071
2072 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002073 if ((q = strchr(p, '=')) == NULL) {
2074 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002075 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002076 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002077
2078 key = alloca(q - p + 6);
2079 memcpy(key, "parm_", 5);
2080 memcpy(key + 5, p, q - p);
2081 key[q - p + 5] = 0;
2082
2083 p = get_modinfo_value(f, key);
2084 key += 5;
2085 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002086 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002087 return 0;
2088 }
2089
2090 sym = obj_find_symbol(f, key);
2091
2092 /* Also check that the parameter was not resolved from the kernel. */
2093 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002094 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002095 return 0;
2096 }
2097
2098 if (isdigit(*p)) {
2099 min = strtoul(p, &p, 10);
2100 if (*p == '-')
2101 max = strtoul(p + 1, &p, 10);
2102 else
2103 max = min;
2104 } else
2105 min = max = 1;
2106
2107 contents = f->sections[sym->secidx]->contents;
2108 loc = contents + sym->value;
2109 n = (*++q != '\0');
2110
2111 while (1) {
2112 if ((*p == 's') || (*p == 'c')) {
2113 char *str;
2114
2115 /* Do C quoting if we begin with a ", else slurp the lot. */
2116 if (*q == '"') {
2117 char *r;
2118
2119 str = alloca(strlen(q));
2120 for (r = str, q++; *q != '"'; ++q, ++r) {
2121 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002122 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002123 key);
2124 return 0;
2125 } else if (*q == '\\')
2126 switch (*++q) {
2127 case 'a':
2128 *r = '\a';
2129 break;
2130 case 'b':
2131 *r = '\b';
2132 break;
2133 case 'e':
2134 *r = '\033';
2135 break;
2136 case 'f':
2137 *r = '\f';
2138 break;
2139 case 'n':
2140 *r = '\n';
2141 break;
2142 case 'r':
2143 *r = '\r';
2144 break;
2145 case 't':
2146 *r = '\t';
2147 break;
2148
2149 case '0':
2150 case '1':
2151 case '2':
2152 case '3':
2153 case '4':
2154 case '5':
2155 case '6':
2156 case '7':
2157 {
2158 int c = *q - '0';
2159 if (q[1] >= '0' && q[1] <= '7') {
2160 c = (c * 8) + *++q - '0';
2161 if (q[1] >= '0' && q[1] <= '7')
2162 c = (c * 8) + *++q - '0';
2163 }
2164 *r = c;
2165 }
2166 break;
2167
2168 default:
2169 *r = *q;
2170 break;
2171 } else
2172 *r = *q;
2173 }
2174 *r = '\0';
2175 ++q;
2176 } else {
2177 char *r;
2178
2179 /* In this case, the string is not quoted. We will break
2180 it using the coma (like for ints). If the user wants to
2181 include comas in a string, he just has to quote it */
2182
2183 /* Search the next coma */
2184 r = strchr(q, ',');
2185
2186 /* Found ? */
2187 if (r != (char *) NULL) {
2188 /* Recopy the current field */
2189 str = alloca(r - q + 1);
2190 memcpy(str, q, r - q);
2191
2192 /* I don't know if it is usefull, as the previous case
2193 doesn't null terminate the string ??? */
2194 str[r - q] = '\0';
2195
2196 /* Keep next fields */
2197 q = r;
2198 } else {
2199 /* last string */
2200 str = q;
2201 q = "";
2202 }
2203 }
2204
2205 if (*p == 's') {
2206 /* Normal string */
2207 obj_string_patch(f, sym->secidx, loc - contents, str);
2208 loc += tgt_sizeof_char_p;
2209 } else {
2210 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002211 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002212
2213 /* Get the size of each member */
2214 /* Probably we should do that outside the loop ? */
2215 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002216 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002217 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002218 return 0;
2219 }
2220 charssize = strtoul(p + 1, (char **) NULL, 10);
2221
2222 /* Check length */
2223 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002224 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002225 charssize - 1);
2226 return 0;
2227 }
2228
2229 /* Copy to location */
2230 strcpy((char *) loc, str);
2231 loc += charssize;
2232 }
2233 } else {
2234 long v = strtoul(q, &q, 0);
2235 switch (*p) {
2236 case 'b':
2237 *loc++ = v;
2238 break;
2239 case 'h':
2240 *(short *) loc = v;
2241 loc += tgt_sizeof_short;
2242 break;
2243 case 'i':
2244 *(int *) loc = v;
2245 loc += tgt_sizeof_int;
2246 break;
2247 case 'l':
2248 *(long *) loc = v;
2249 loc += tgt_sizeof_long;
2250 break;
2251
2252 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002253 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002254 return 0;
2255 }
2256 }
2257
2258 retry_end_of_value:
2259 switch (*q) {
2260 case '\0':
2261 goto end_of_arg;
2262
2263 case ' ':
2264 case '\t':
2265 case '\n':
2266 case '\r':
2267 ++q;
2268 goto retry_end_of_value;
2269
2270 case ',':
2271 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002272 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002273 return 0;
2274 }
2275 ++q;
2276 break;
2277
2278 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002279 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002280 return 0;
2281 }
2282 }
2283
2284 end_of_arg:
2285 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002286 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002287 return 0;
2288 }
2289
2290 argc--, argv++;
2291 }
2292
2293 return 1;
2294}
2295
2296#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2297static int new_is_module_checksummed(struct obj_file *f)
2298{
2299 const char *p = get_modinfo_value(f, "using_checksums");
2300 if (p)
2301 return atoi(p);
2302 else
2303 return 0;
2304}
2305
2306/* Get the module's kernel version in the canonical integer form. */
2307
2308static int
2309new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2310{
2311 char *p, *q;
2312 int a, b, c;
2313
2314 p = get_modinfo_value(f, "kernel_version");
2315 if (p == NULL)
2316 return -1;
2317 strncpy(str, p, STRVERSIONLEN);
2318
2319 a = strtoul(p, &p, 10);
2320 if (*p != '.')
2321 return -1;
2322 b = strtoul(p + 1, &p, 10);
2323 if (*p != '.')
2324 return -1;
2325 c = strtoul(p + 1, &q, 10);
2326 if (p + 1 == q)
2327 return -1;
2328
2329 return a << 16 | b << 8 | c;
2330}
2331
2332#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2333
2334
Eric Andersenf5d5e772001-01-24 23:34:48 +00002335#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002336
2337/* Fetch the loaded modules, and all currently exported symbols. */
2338
2339static int new_get_kernel_symbols(void)
2340{
2341 char *module_names, *mn;
2342 struct external_module *modules, *m;
2343 struct new_module_symbol *syms, *s;
2344 size_t ret, bufsize, nmod, nsyms, i, j;
2345
2346 /* Collect the loaded modules. */
2347
2348 module_names = xmalloc(bufsize = 256);
2349 retry_modules_load:
2350 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002351 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002352 module_names = xrealloc(module_names, bufsize = ret);
2353 goto retry_modules_load;
2354 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002355 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002356 return 0;
2357 }
2358
2359 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002360
2361 /* Collect the modules' symbols. */
2362
Mark Whitley94fd4802001-03-12 23:08:34 +00002363 if (nmod){
2364 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2365 memset(modules, 0, nmod * sizeof(*modules));
2366 for (i = 0, mn = module_names, m = modules;
2367 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2368 struct new_module_info info;
2369
2370 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2371 if (errno == ENOENT) {
2372 /* The module was removed out from underneath us. */
2373 continue;
2374 }
2375 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002376 return 0;
2377 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002378
2379 syms = xmalloc(bufsize = 1024);
2380 retry_mod_sym_load:
2381 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2382 switch (errno) {
2383 case ENOSPC:
2384 syms = xrealloc(syms, bufsize = ret);
2385 goto retry_mod_sym_load;
2386 case ENOENT:
2387 /* The module was removed out from underneath us. */
2388 continue;
2389 default:
2390 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2391 return 0;
2392 }
2393 }
2394 nsyms = ret;
2395
2396 m->name = mn;
2397 m->addr = info.addr;
2398 m->nsyms = nsyms;
2399 m->syms = syms;
2400
2401 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2402 s->name += (unsigned long) syms;
2403 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002404 }
2405 }
2406
2407 /* Collect the kernel's symbols. */
2408
2409 syms = xmalloc(bufsize = 16 * 1024);
2410 retry_kern_sym_load:
2411 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002412 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002413 syms = xrealloc(syms, bufsize = ret);
2414 goto retry_kern_sym_load;
2415 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002416 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002417 return 0;
2418 }
2419 nksyms = nsyms = ret;
2420 ksyms = syms;
2421
2422 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2423 s->name += (unsigned long) syms;
2424 }
2425 return 1;
2426}
2427
2428
2429/* Return the kernel symbol checksum version, or zero if not used. */
2430
2431static int new_is_kernel_checksummed(void)
2432{
2433 struct new_module_symbol *s;
2434 size_t i;
2435
2436 /* Using_Versions is not the first symbol, but it should be in there. */
2437
2438 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2439 if (strcmp((char *) s->name, "Using_Versions") == 0)
2440 return s->value;
2441
2442 return 0;
2443}
2444
2445
2446static int new_create_this_module(struct obj_file *f, const char *m_name)
2447{
2448 struct obj_section *sec;
2449
2450 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2451 sizeof(struct new_module));
2452 memset(sec->contents, 0, sizeof(struct new_module));
2453
2454 obj_add_symbol(f, "__this_module", -1,
2455 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2456 sizeof(struct new_module));
2457
2458 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2459 m_name);
2460
2461 return 1;
2462}
2463
2464
2465static int new_create_module_ksymtab(struct obj_file *f)
2466{
2467 struct obj_section *sec;
2468 int i;
2469
2470 /* We must always add the module references. */
2471
2472 if (n_ext_modules_used) {
2473 struct new_module_ref *dep;
2474 struct obj_symbol *tm;
2475
2476 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2477 (sizeof(struct new_module_ref)
2478 * n_ext_modules_used));
2479 if (!sec)
2480 return 0;
2481
2482 tm = obj_find_symbol(f, "__this_module");
2483 dep = (struct new_module_ref *) sec->contents;
2484 for (i = 0; i < n_ext_modules; ++i)
2485 if (ext_modules[i].used) {
2486 dep->dep = ext_modules[i].addr;
2487 obj_symbol_patch(f, sec->idx,
2488 (char *) &dep->ref - sec->contents, tm);
2489 dep->next_ref = 0;
2490 ++dep;
2491 }
2492 }
2493
2494 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2495 size_t nsyms;
2496 int *loaded;
2497
2498 sec =
2499 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2500 0);
2501
2502 /* We don't want to export symbols residing in sections that
2503 aren't loaded. There are a number of these created so that
2504 we make sure certain module options don't appear twice. */
2505
2506 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2507 while (--i >= 0)
2508 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2509
2510 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2511 struct obj_symbol *sym;
2512 for (sym = f->symtab[i]; sym; sym = sym->next)
2513 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2514 && sym->secidx <= SHN_HIRESERVE
2515 && (sym->secidx >= SHN_LORESERVE
2516 || loaded[sym->secidx])) {
2517 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2518
2519 obj_symbol_patch(f, sec->idx, ofs, sym);
2520 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2521 sym->name);
2522
2523 nsyms++;
2524 }
2525 }
2526
2527 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2528 }
2529
2530 return 1;
2531}
2532
2533
2534static int
2535new_init_module(const char *m_name, struct obj_file *f,
2536 unsigned long m_size)
2537{
2538 struct new_module *module;
2539 struct obj_section *sec;
2540 void *image;
2541 int ret;
2542 tgt_long m_addr;
2543
2544 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002545 if (!sec || !sec->contents) {
2546 perror_msg_and_die("corrupt module %s?",m_name);
2547 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002548 module = (struct new_module *) sec->contents;
2549 m_addr = sec->header.sh_addr;
2550
2551 module->size_of_struct = sizeof(*module);
2552 module->size = m_size;
2553 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2554
2555 sec = obj_find_section(f, "__ksymtab");
2556 if (sec && sec->header.sh_size) {
2557 module->syms = sec->header.sh_addr;
2558 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2559 }
2560
2561 if (n_ext_modules_used) {
2562 sec = obj_find_section(f, ".kmodtab");
2563 module->deps = sec->header.sh_addr;
2564 module->ndeps = n_ext_modules_used;
2565 }
2566
2567 module->init =
2568 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2569 module->cleanup =
2570 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2571
2572 sec = obj_find_section(f, "__ex_table");
2573 if (sec) {
2574 module->ex_table_start = sec->header.sh_addr;
2575 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2576 }
2577
2578 sec = obj_find_section(f, ".text.init");
2579 if (sec) {
2580 module->runsize = sec->header.sh_addr - m_addr;
2581 }
2582 sec = obj_find_section(f, ".data.init");
2583 if (sec) {
2584 if (!module->runsize ||
2585 module->runsize > sec->header.sh_addr - m_addr)
2586 module->runsize = sec->header.sh_addr - m_addr;
2587 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002588 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2589 if (sec && sec->header.sh_size) {
2590 module->archdata_start = (void*)sec->header.sh_addr;
2591 module->archdata_end = module->archdata_start + sec->header.sh_size;
2592 }
2593 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2594 if (sec && sec->header.sh_size) {
2595 module->kallsyms_start = (void*)sec->header.sh_addr;
2596 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2597 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002598
2599 if (!arch_init_module(f, module))
2600 return 0;
2601
2602 /* Whew! All of the initialization is complete. Collect the final
2603 module image and give it to the kernel. */
2604
2605 image = xmalloc(m_size);
2606 obj_create_image(f, image);
2607
Eric Andersen64c8b172001-04-05 07:33:10 +00002608 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002609 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002610 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002611
2612 free(image);
2613
2614 return ret == 0;
2615}
2616
2617#else
2618
2619#define new_init_module(x, y, z) TRUE
2620#define new_create_this_module(x, y) 0
2621#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002622#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002623
Eric Andersenf5d5e772001-01-24 23:34:48 +00002624#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002625
2626
2627/*======================================================================*/
2628
2629int
2630obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2631 const char *string)
2632{
2633 struct obj_string_patch *p;
2634 struct obj_section *strsec;
2635 size_t len = strlen(string) + 1;
2636 char *loc;
2637
2638 p = xmalloc(sizeof(*p));
2639 p->next = f->string_patches;
2640 p->reloc_secidx = secidx;
2641 p->reloc_offset = offset;
2642 f->string_patches = p;
2643
2644 strsec = obj_find_section(f, ".kstrtab");
2645 if (strsec == NULL) {
2646 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2647 p->string_offset = 0;
2648 loc = strsec->contents;
2649 } else {
2650 p->string_offset = strsec->header.sh_size;
2651 loc = obj_extend_section(strsec, len);
2652 }
2653 memcpy(loc, string, len);
2654
2655 return 1;
2656}
2657
2658int
2659obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2660 struct obj_symbol *sym)
2661{
2662 struct obj_symbol_patch *p;
2663
2664 p = xmalloc(sizeof(*p));
2665 p->next = f->symbol_patches;
2666 p->reloc_secidx = secidx;
2667 p->reloc_offset = offset;
2668 p->sym = sym;
2669 f->symbol_patches = p;
2670
2671 return 1;
2672}
2673
2674int obj_check_undefineds(struct obj_file *f)
2675{
2676 unsigned long i;
2677 int ret = 1;
2678
2679 for (i = 0; i < HASH_BUCKETS; ++i) {
2680 struct obj_symbol *sym;
2681 for (sym = f->symtab[i]; sym; sym = sym->next)
2682 if (sym->secidx == SHN_UNDEF) {
2683 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2684 sym->secidx = SHN_ABS;
2685 sym->value = 0;
2686 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002687 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002688 ret = 0;
2689 }
2690 }
2691 }
2692
2693 return ret;
2694}
2695
2696void obj_allocate_commons(struct obj_file *f)
2697{
2698 struct common_entry {
2699 struct common_entry *next;
2700 struct obj_symbol *sym;
2701 } *common_head = NULL;
2702
2703 unsigned long i;
2704
2705 for (i = 0; i < HASH_BUCKETS; ++i) {
2706 struct obj_symbol *sym;
2707 for (sym = f->symtab[i]; sym; sym = sym->next)
2708 if (sym->secidx == SHN_COMMON) {
2709 /* Collect all COMMON symbols and sort them by size so as to
2710 minimize space wasted by alignment requirements. */
2711 {
2712 struct common_entry **p, *n;
2713 for (p = &common_head; *p; p = &(*p)->next)
2714 if (sym->size <= (*p)->sym->size)
2715 break;
2716
2717 n = alloca(sizeof(*n));
2718 n->next = *p;
2719 n->sym = sym;
2720 *p = n;
2721 }
2722 }
2723 }
2724
2725 for (i = 1; i < f->local_symtab_size; ++i) {
2726 struct obj_symbol *sym = f->local_symtab[i];
2727 if (sym && sym->secidx == SHN_COMMON) {
2728 struct common_entry **p, *n;
2729 for (p = &common_head; *p; p = &(*p)->next)
2730 if (sym == (*p)->sym)
2731 break;
2732 else if (sym->size < (*p)->sym->size) {
2733 n = alloca(sizeof(*n));
2734 n->next = *p;
2735 n->sym = sym;
2736 *p = n;
2737 break;
2738 }
2739 }
2740 }
2741
2742 if (common_head) {
2743 /* Find the bss section. */
2744 for (i = 0; i < f->header.e_shnum; ++i)
2745 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2746 break;
2747
2748 /* If for some reason there hadn't been one, create one. */
2749 if (i == f->header.e_shnum) {
2750 struct obj_section *sec;
2751
2752 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2753 f->sections[i] = sec = arch_new_section();
2754 f->header.e_shnum = i + 1;
2755
2756 memset(sec, 0, sizeof(*sec));
2757 sec->header.sh_type = SHT_PROGBITS;
2758 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2759 sec->name = ".bss";
2760 sec->idx = i;
2761 }
2762
2763 /* Allocate the COMMONS. */
2764 {
2765 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2766 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2767 struct common_entry *c;
2768
2769 for (c = common_head; c; c = c->next) {
2770 ElfW(Addr) align = c->sym->value;
2771
2772 if (align > max_align)
2773 max_align = align;
2774 if (bss_size & (align - 1))
2775 bss_size = (bss_size | (align - 1)) + 1;
2776
2777 c->sym->secidx = i;
2778 c->sym->value = bss_size;
2779
2780 bss_size += c->sym->size;
2781 }
2782
2783 f->sections[i]->header.sh_size = bss_size;
2784 f->sections[i]->header.sh_addralign = max_align;
2785 }
2786 }
2787
2788 /* For the sake of patch relocation and parameter initialization,
2789 allocate zeroed data for NOBITS sections now. Note that after
2790 this we cannot assume NOBITS are really empty. */
2791 for (i = 0; i < f->header.e_shnum; ++i) {
2792 struct obj_section *s = f->sections[i];
2793 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002794 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002795 s->contents = memset(xmalloc(s->header.sh_size),
2796 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002797 else
2798 s->contents = NULL;
2799
Eric Andersen9f16d612000-06-12 23:11:16 +00002800 s->header.sh_type = SHT_PROGBITS;
2801 }
2802 }
2803}
2804
2805unsigned long obj_load_size(struct obj_file *f)
2806{
2807 unsigned long dot = 0;
2808 struct obj_section *sec;
2809
2810 /* Finalize the positions of the sections relative to one another. */
2811
2812 for (sec = f->load_order; sec; sec = sec->load_next) {
2813 ElfW(Addr) align;
2814
2815 align = sec->header.sh_addralign;
2816 if (align && (dot & (align - 1)))
2817 dot = (dot | (align - 1)) + 1;
2818
2819 sec->header.sh_addr = dot;
2820 dot += sec->header.sh_size;
2821 }
2822
2823 return dot;
2824}
2825
2826int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2827{
2828 int i, n = f->header.e_shnum;
2829 int ret = 1;
2830
2831 /* Finalize the addresses of the sections. */
2832
2833 f->baseaddr = base;
2834 for (i = 0; i < n; ++i)
2835 f->sections[i]->header.sh_addr += base;
2836
2837 /* And iterate over all of the relocations. */
2838
2839 for (i = 0; i < n; ++i) {
2840 struct obj_section *relsec, *symsec, *targsec, *strsec;
2841 ElfW(RelM) * rel, *relend;
2842 ElfW(Sym) * symtab;
2843 const char *strtab;
2844
2845 relsec = f->sections[i];
2846 if (relsec->header.sh_type != SHT_RELM)
2847 continue;
2848
2849 symsec = f->sections[relsec->header.sh_link];
2850 targsec = f->sections[relsec->header.sh_info];
2851 strsec = f->sections[symsec->header.sh_link];
2852
2853 rel = (ElfW(RelM) *) relsec->contents;
2854 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2855 symtab = (ElfW(Sym) *) symsec->contents;
2856 strtab = (const char *) strsec->contents;
2857
2858 for (; rel < relend; ++rel) {
2859 ElfW(Addr) value = 0;
2860 struct obj_symbol *intsym = NULL;
2861 unsigned long symndx;
2862 ElfW(Sym) * extsym = 0;
2863 const char *errmsg;
2864
2865 /* Attempt to find a value to use for this relocation. */
2866
2867 symndx = ELFW(R_SYM) (rel->r_info);
2868 if (symndx) {
2869 /* Note we've already checked for undefined symbols. */
2870
2871 extsym = &symtab[symndx];
2872 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2873 /* Local symbols we look up in the local table to be sure
2874 we get the one that is really intended. */
2875 intsym = f->local_symtab[symndx];
2876 } else {
2877 /* Others we look up in the hash table. */
2878 const char *name;
2879 if (extsym->st_name)
2880 name = strtab + extsym->st_name;
2881 else
2882 name = f->sections[extsym->st_shndx]->name;
2883 intsym = obj_find_symbol(f, name);
2884 }
2885
2886 value = obj_symbol_final_value(f, intsym);
2887 intsym->referenced = 1;
2888 }
2889#if SHT_RELM == SHT_RELA
2890#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2891 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2892 if (!extsym || !extsym->st_name ||
2893 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2894#endif
2895 value += rel->r_addend;
2896#endif
2897
2898 /* Do it! */
2899 switch (arch_apply_relocation
2900 (f, targsec, symsec, intsym, rel, value)) {
2901 case obj_reloc_ok:
2902 break;
2903
2904 case obj_reloc_overflow:
2905 errmsg = "Relocation overflow";
2906 goto bad_reloc;
2907 case obj_reloc_dangerous:
2908 errmsg = "Dangerous relocation";
2909 goto bad_reloc;
2910 case obj_reloc_unhandled:
2911 errmsg = "Unhandled relocation";
2912 bad_reloc:
2913 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002914 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002915 (long) ELFW(R_TYPE) (rel->r_info),
2916 strtab + extsym->st_name);
2917 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002918 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002919 (long) ELFW(R_TYPE) (rel->r_info));
2920 }
2921 ret = 0;
2922 break;
2923 }
2924 }
2925 }
2926
2927 /* Finally, take care of the patches. */
2928
2929 if (f->string_patches) {
2930 struct obj_string_patch *p;
2931 struct obj_section *strsec;
2932 ElfW(Addr) strsec_base;
2933 strsec = obj_find_section(f, ".kstrtab");
2934 strsec_base = strsec->header.sh_addr;
2935
2936 for (p = f->string_patches; p; p = p->next) {
2937 struct obj_section *targsec = f->sections[p->reloc_secidx];
2938 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2939 = strsec_base + p->string_offset;
2940 }
2941 }
2942
2943 if (f->symbol_patches) {
2944 struct obj_symbol_patch *p;
2945
2946 for (p = f->symbol_patches; p; p = p->next) {
2947 struct obj_section *targsec = f->sections[p->reloc_secidx];
2948 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2949 = obj_symbol_final_value(f, p->sym);
2950 }
2951 }
2952
2953 return ret;
2954}
2955
2956int obj_create_image(struct obj_file *f, char *image)
2957{
2958 struct obj_section *sec;
2959 ElfW(Addr) base = f->baseaddr;
2960
2961 for (sec = f->load_order; sec; sec = sec->load_next) {
2962 char *secimg;
2963
Eric Andersen2bf658d2001-02-24 20:01:53 +00002964 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002965 continue;
2966
2967 secimg = image + (sec->header.sh_addr - base);
2968
2969 /* Note that we allocated data for NOBITS sections earlier. */
2970 memcpy(secimg, sec->contents, sec->header.sh_size);
2971 }
2972
2973 return 1;
2974}
2975
2976/*======================================================================*/
2977
Eric Andersen8ae319a2001-05-21 16:09:18 +00002978struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002979{
2980 struct obj_file *f;
2981 ElfW(Shdr) * section_headers;
2982 int shnum, i;
2983 char *shstrtab;
2984
2985 /* Read the file header. */
2986
2987 f = arch_new_file();
2988 memset(f, 0, sizeof(*f));
2989 f->symbol_cmp = strcmp;
2990 f->symbol_hash = obj_elf_hash;
2991 f->load_order_search_start = &f->load_order;
2992
2993 fseek(fp, 0, SEEK_SET);
2994 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002995 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002996 return NULL;
2997 }
2998
2999 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3000 || f->header.e_ident[EI_MAG1] != ELFMAG1
3001 || f->header.e_ident[EI_MAG2] != ELFMAG2
3002 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003003 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003004 return NULL;
3005 }
3006 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3007 || f->header.e_ident[EI_DATA] != ELFDATAM
3008 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3009 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003010 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003011 return NULL;
3012 }
3013 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003014 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 return NULL;
3016 }
3017
3018 /* Read the section headers. */
3019
3020 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003021 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003022 (unsigned long) f->header.e_shentsize,
3023 (unsigned long) sizeof(ElfW(Shdr)));
3024 return NULL;
3025 }
3026
3027 shnum = f->header.e_shnum;
3028 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3029 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3030
3031 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3032 fseek(fp, f->header.e_shoff, SEEK_SET);
3033 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003034 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003035 return NULL;
3036 }
3037
3038 /* Read the section data. */
3039
3040 for (i = 0; i < shnum; ++i) {
3041 struct obj_section *sec;
3042
3043 f->sections[i] = sec = arch_new_section();
3044 memset(sec, 0, sizeof(*sec));
3045
3046 sec->header = section_headers[i];
3047 sec->idx = i;
3048
Eric Andersen2bf658d2001-02-24 20:01:53 +00003049 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003050 case SHT_NULL:
3051 case SHT_NOTE:
3052 case SHT_NOBITS:
3053 /* ignore */
3054 break;
3055
3056 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003057#if LOADBITS
3058 if (!loadprogbits) {
3059 sec->contents = NULL;
3060 break;
3061 }
3062#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003063 case SHT_SYMTAB:
3064 case SHT_STRTAB:
3065 case SHT_RELM:
3066 if (sec->header.sh_size > 0) {
3067 sec->contents = xmalloc(sec->header.sh_size);
3068 fseek(fp, sec->header.sh_offset, SEEK_SET);
3069 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003070 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003071 return NULL;
3072 }
3073 } else {
3074 sec->contents = NULL;
3075 }
3076 break;
3077
3078#if SHT_RELM == SHT_REL
3079 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003080 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003081 return NULL;
3082#else
3083 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003084 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003085 return NULL;
3086#endif
3087
3088 default:
3089 if (sec->header.sh_type >= SHT_LOPROC) {
3090 /* Assume processor specific section types are debug
3091 info and can safely be ignored. If this is ever not
3092 the case (Hello MIPS?), don't put ifdefs here but
3093 create an arch_load_proc_section(). */
3094 break;
3095 }
3096
Matt Kraaidd19c692001-01-31 19:00:21 +00003097 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003098 (long) sec->header.sh_type);
3099 return NULL;
3100 }
3101 }
3102
3103 /* Do what sort of interpretation as needed by each section. */
3104
3105 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3106
3107 for (i = 0; i < shnum; ++i) {
3108 struct obj_section *sec = f->sections[i];
3109 sec->name = shstrtab + sec->header.sh_name;
3110 }
3111
3112 for (i = 0; i < shnum; ++i) {
3113 struct obj_section *sec = f->sections[i];
3114
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003115 /* .modinfo should be contents only but gcc has no attribute for that.
3116 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3117 */
3118 if (strcmp(sec->name, ".modinfo") == 0)
3119 sec->header.sh_flags &= ~SHF_ALLOC;
3120
Eric Andersen9f16d612000-06-12 23:11:16 +00003121 if (sec->header.sh_flags & SHF_ALLOC)
3122 obj_insert_section_load_order(f, sec);
3123
3124 switch (sec->header.sh_type) {
3125 case SHT_SYMTAB:
3126 {
3127 unsigned long nsym, j;
3128 char *strtab;
3129 ElfW(Sym) * sym;
3130
3131 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003132 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003133 (unsigned long) sec->header.sh_entsize,
3134 (unsigned long) sizeof(ElfW(Sym)));
3135 return NULL;
3136 }
3137
3138 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3139 strtab = f->sections[sec->header.sh_link]->contents;
3140 sym = (ElfW(Sym) *) sec->contents;
3141
3142 /* Allocate space for a table of local symbols. */
3143 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003144 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003145
3146 /* Insert all symbols into the hash table. */
3147 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3148 const char *name;
3149 if (sym->st_name)
3150 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003151 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003152 name = f->sections[sym->st_shndx]->name;
3153
3154 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3155 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003156 }
3157 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003158 break;
3159
3160 case SHT_RELM:
3161 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003162 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003163 (unsigned long) sec->header.sh_entsize,
3164 (unsigned long) sizeof(ElfW(RelM)));
3165 return NULL;
3166 }
3167 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003168 /* XXX Relocation code from modutils-2.3.19 is not here.
3169 * Why? That's about 20 lines of code from obj/obj_load.c,
3170 * which gets done in a second pass through the sections.
3171 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003172 }
3173 }
3174
3175 return f;
3176}
3177
Eric Andersen8ae319a2001-05-21 16:09:18 +00003178#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3179/*
3180 * load the unloaded sections directly into the memory allocated by
3181 * kernel for the module
3182 */
3183
3184int obj_load_progbits(FILE * fp, struct obj_file* f)
3185{
3186 char* imagebase = (char*) f->imagebase;
3187 ElfW(Addr) base = f->baseaddr;
3188 struct obj_section* sec;
3189
3190 for (sec = f->load_order; sec; sec = sec->load_next) {
3191
3192 /* section already loaded? */
3193 if (sec->contents != NULL)
3194 continue;
3195
3196 if (sec->header.sh_size == 0)
3197 continue;
3198
3199 sec->contents = imagebase + (sec->header.sh_addr - base);
3200 fseek(fp, sec->header.sh_offset, SEEK_SET);
3201 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3202 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3203 return 0;
3204 }
3205
3206 }
3207 return 1;
3208}
3209#endif
3210
Eric Andersen9f16d612000-06-12 23:11:16 +00003211static void hide_special_symbols(struct obj_file *f)
3212{
3213 static const char *const specials[] = {
3214 "cleanup_module",
3215 "init_module",
3216 "kernel_version",
3217 NULL
3218 };
3219
3220 struct obj_symbol *sym;
3221 const char *const *p;
3222
3223 for (p = specials; *p; ++p)
3224 if ((sym = obj_find_symbol(f, *p)) != NULL)
3225 sym->info =
3226 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3227}
3228
3229
3230
3231extern int insmod_main( int argc, char **argv)
3232{
Eric Andersena18aaf12001-01-24 19:07:09 +00003233 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003234 int k_crcs;
3235 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003236 int len;
3237 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003238 unsigned long m_size;
3239 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003240 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003241 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003242 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003243 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003244 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003245 int m_has_modinfo;
3246#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3247 int k_version;
3248 char k_strversion[STRVERSIONLEN];
3249 char m_strversion[STRVERSIONLEN];
3250 int m_version;
3251 int m_crcs;
3252#endif
3253
Erik Andersene49d5ec2000-02-08 19:58:47 +00003254 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003255 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003256 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003257 case 'f': /* force loading */
3258 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003259 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003260 case 'k': /* module loaded by kerneld, auto-cleanable */
3261 flag_autoclean = 1;
3262 break;
3263 case 'v': /* verbose output */
3264 flag_verbose = 1;
3265 break;
3266 case 'x': /* do not export externs */
3267 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003268 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003269 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003270 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003271 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003272 case 'L': /* Stub warning */
3273 /* This is needed for compatibility with modprobe.
3274 * In theory, this does locking, but we don't do
3275 * that. So be careful and plan your life around not
3276 * loading the same module 50 times concurrently. */
3277 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003278 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003279 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003280 }
Erik Andersend387d011999-12-21 02:55:11 +00003281 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003282
3283 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003284 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003285 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003286
Erik Andersene49d5ec2000-02-08 19:58:47 +00003287 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003288 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003289 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003290 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003291 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003292 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003293 len = strlen(tmp);
3294
3295 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3296 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003297 memcpy(m_fullName, tmp, len);
3298 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003299 if (*m_name == '\0') {
3300 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003301 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003302 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003303
Eric Andersen14d35432001-05-14 17:07:32 +00003304 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003305 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3306 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003307 struct utsname myuname;
3308
3309 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3310 * but do not error out yet if we fail to find it... */
3311 if (uname(&myuname) == 0) {
3312 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003313 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003314 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3315 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003316 /* Jump through hoops in case /lib/modules/`uname -r`
3317 * is a symlink. We do not want recursive_action to
3318 * follow symlinks, but we do want to follow the
3319 * /lib/modules/`uname -r` dir, So resolve it ourselves
3320 * if it is a link... */
3321 if (realpath (module_dir, real_module_dir) == NULL)
3322 strcpy(real_module_dir, module_dir);
3323 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003324 check_module_name_match, 0, m_fullName);
3325 }
3326
3327 /* Check if we have found anything yet */
3328 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003329 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003330 char module_dir[FILENAME_MAX];
3331 if (realpath (_PATH_MODULES, module_dir) == NULL)
3332 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003333 /* No module found under /lib/modules/`uname -r`, this
3334 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003335 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003336 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003337 {
Eric Andersen14d35432001-05-14 17:07:32 +00003338 if (m_filename[0] == '\0'
3339 || ((fp = fopen(m_filename, "r")) == NULL))
3340 {
3341 error_msg("%s: no module by that name found", m_fullName);
3342 return EXIT_FAILURE;
3343 }
3344 } else
3345 error_msg_and_die("%s: no module by that name found", m_fullName);
3346 }
3347 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003348 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003349
Eric Andersen14d35432001-05-14 17:07:32 +00003350 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003351
Eric Andersen8ae319a2001-05-21 16:09:18 +00003352 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003353 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003354
Eric Andersen9f16d612000-06-12 23:11:16 +00003355 if (get_modinfo_value(f, "kernel_version") == NULL)
3356 m_has_modinfo = 0;
3357 else
3358 m_has_modinfo = 1;
3359
3360#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3361 /* Version correspondence? */
3362
3363 k_version = get_kernel_version(k_strversion);
3364 if (m_has_modinfo) {
3365 m_version = new_get_module_version(f, m_strversion);
3366 } else {
3367 m_version = old_get_module_version(f, m_strversion);
3368 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003369 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003370 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003371 goto out;
3372 }
3373 }
3374
3375 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3376 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003377 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003379 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 m_filename, m_strversion, k_strversion);
3381 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003382 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003383 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003384 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003385 m_filename, m_strversion, k_strversion);
3386 goto out;
3387 }
3388 }
3389 k_crcs = 0;
3390#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3391
3392 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3393
3394 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003395#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 if (!new_get_kernel_symbols())
3397 goto out;
3398 k_crcs = new_is_kernel_checksummed();
3399#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003400 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003401 goto out;
3402#endif
3403 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003404#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003405 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003406 goto out;
3407 k_crcs = old_is_kernel_checksummed();
3408#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003409 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003410 goto out;
3411#endif
3412 }
3413
3414#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3415 if (m_has_modinfo)
3416 m_crcs = new_is_module_checksummed(f);
3417 else
3418 m_crcs = old_is_module_checksummed(f);
3419
3420 if (m_crcs != k_crcs)
3421 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3422#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3423
Erik Andersene49d5ec2000-02-08 19:58:47 +00003424 /* Let the module know about the kernel symbols. */
3425 add_kernel_symbols(f);
3426
Eric Andersen9f16d612000-06-12 23:11:16 +00003427 /* Allocate common symbols, symbol tables, and string tables. */
3428
3429 if (k_new_syscalls
3430 ? !new_create_this_module(f, m_name)
3431 : !old_create_mod_use_count(f))
3432 {
3433 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003434 }
3435
Eric Andersen9f16d612000-06-12 23:11:16 +00003436 if (!obj_check_undefineds(f)) {
3437 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003438 }
3439 obj_allocate_commons(f);
3440
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003441 /* done with the module name, on to the optional var=value arguments */
3442 ++optind;
3443
Eric Andersen9f16d612000-06-12 23:11:16 +00003444 if (optind < argc) {
3445 if (m_has_modinfo
3446 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3447 : !old_process_module_arguments(f, argc - optind, argv + optind))
3448 {
3449 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003450 }
3451 }
3452
Eric Andersen9f16d612000-06-12 23:11:16 +00003453 arch_create_got(f);
3454 hide_special_symbols(f);
3455
3456 if (k_new_syscalls)
3457 new_create_module_ksymtab(f);
3458
Erik Andersene49d5ec2000-02-08 19:58:47 +00003459 /* Find current size of the module */
3460 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003461
3462
Erik Andersene49d5ec2000-02-08 19:58:47 +00003463 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003464 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003465 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003466 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003467 goto out;
3468 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003469 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003470 m_size);
3471 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003472 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003473 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003474 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003475 }
Erik Andersend387d011999-12-21 02:55:11 +00003476
Eric Andersen8ae319a2001-05-21 16:09:18 +00003477#if !LOADBITS
3478 /*
3479 * the PROGBITS section was not loaded by the obj_load
3480 * now we can load them directly into the kernel memory
3481 */
3482 // f->imagebase = (char*) m_addr;
3483 f->imagebase = (ElfW(Addr)) m_addr;
3484 if (!obj_load_progbits(fp, f)) {
3485 delete_module(m_name);
3486 goto out;
3487 }
3488#endif
3489
Eric Andersen9f16d612000-06-12 23:11:16 +00003490 if (!obj_relocate(f, m_addr)) {
3491 delete_module(m_name);
3492 goto out;
3493 }
Erik Andersend387d011999-12-21 02:55:11 +00003494
Eric Andersen9f16d612000-06-12 23:11:16 +00003495 if (k_new_syscalls
3496 ? !new_init_module(m_name, f, m_size)
3497 : !old_init_module(m_name, f, m_size))
3498 {
3499 delete_module(m_name);
3500 goto out;
3501 }
3502
Matt Kraai3e856ce2000-12-01 02:55:13 +00003503 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003504
3505out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003506 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003507 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003508}