blob: 4b00515942fb7d756a239dcef08eec95a308a14e [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 Andersen66ca9482001-06-28 21:36:06 +0000133#ident "$Id: insmod.c,v 1.67 2001/06/28 21:36:06 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 Andersen66ca9482001-06-28 21:36:06 +0000350#ident "$Id: insmod.c,v 1.67 2001/06/28 21:36:06 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 Andersenb4a26e62001-06-19 15:00:52 +0000375#if (defined(__mc68000__))
Eric Andersen8ae319a2001-05-21 16:09:18 +0000376#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 Andersenb4a26e62001-06-19 15:00:52 +0000438#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000439
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 Andersenb4a26e62001-06-19 15:00:52 +0000816#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000817 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 Andersenb4a26e62001-06-19 15:00:52 +0000831#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000832 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 Andersenb4a26e62001-06-19 15:00:52 +0000840#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000841 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;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000851#endif /* __mc68000__ */
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 Andersenb4a26e62001-06-19 15:00:52 +0000957#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000958 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 Andersenb4a26e62001-06-19 15:00:52 +00001052#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001053 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 Andersenb4a26e62001-06-19 15:00:52 +00001068#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001069 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 Andersenb4a26e62001-06-19 15:00:52 +00001099#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001100 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 Andersenb4a26e62001-06-19 15:00:52 +00001111#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
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 Andersenb4a26e62001-06-19 15:00:52 +00001117#if !defined(__mc68000__)
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 Andersenb4a26e62001-06-19 15:00:52 +00001124#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001125 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 Andersenb4a26e62001-06-19 15:00:52 +00001130#endif // __mc68000__
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 Andersenb4a26e62001-06-19 15:00:52 +00001186#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001187 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
Eric Andersen66ca9482001-06-28 21:36:06 +00001463 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1464 if (symidx >= f->local_symtab_size)
1465 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1466 name, (long) symidx, (long) f->local_symtab_size);
1467 else
1468 f->local_symtab[symidx] = sym;
1469 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001470
1471 found:
1472 sym->name = name;
1473 sym->value = value;
1474 sym->size = size;
1475 sym->secidx = secidx;
1476 sym->info = info;
1477
1478 return sym;
1479}
1480
1481struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1482{
1483 struct obj_symbol *sym;
1484 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1485
1486 for (sym = f->symtab[hash]; sym; sym = sym->next)
1487 if (f->symbol_cmp(sym->name, name) == 0)
1488 return sym;
1489
1490 return NULL;
1491}
1492
1493ElfW(Addr)
1494 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1495{
1496 if (sym) {
1497 if (sym->secidx >= SHN_LORESERVE)
1498 return sym->value;
1499
1500 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1501 } else {
1502 /* As a special case, a NULL sym has value zero. */
1503 return 0;
1504 }
1505}
1506
1507struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1508{
1509 int i, n = f->header.e_shnum;
1510
1511 for (i = 0; i < n; ++i)
1512 if (strcmp(f->sections[i]->name, name) == 0)
1513 return f->sections[i];
1514
1515 return NULL;
1516}
1517
1518static int obj_load_order_prio(struct obj_section *a)
1519{
1520 unsigned long af, ac;
1521
1522 af = a->header.sh_flags;
1523
1524 ac = 0;
1525 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1526 strcmp(a->name + 5, ".init"))
1527 ac |= 32;
1528 if (af & SHF_ALLOC)
1529 ac |= 16;
1530 if (!(af & SHF_WRITE))
1531 ac |= 8;
1532 if (af & SHF_EXECINSTR)
1533 ac |= 4;
1534 if (a->header.sh_type != SHT_NOBITS)
1535 ac |= 2;
1536
1537 return ac;
1538}
1539
1540void
1541obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1542{
1543 struct obj_section **p;
1544 int prio = obj_load_order_prio(sec);
1545 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1546 if (obj_load_order_prio(*p) < prio)
1547 break;
1548 sec->load_next = *p;
1549 *p = sec;
1550}
1551
1552struct obj_section *obj_create_alloced_section(struct obj_file *f,
1553 const char *name,
1554 unsigned long align,
1555 unsigned long size)
1556{
1557 int newidx = f->header.e_shnum++;
1558 struct obj_section *sec;
1559
1560 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1561 f->sections[newidx] = sec = arch_new_section();
1562
1563 memset(sec, 0, sizeof(*sec));
1564 sec->header.sh_type = SHT_PROGBITS;
1565 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1566 sec->header.sh_size = size;
1567 sec->header.sh_addralign = align;
1568 sec->name = name;
1569 sec->idx = newidx;
1570 if (size)
1571 sec->contents = xmalloc(size);
1572
1573 obj_insert_section_load_order(f, sec);
1574
1575 return sec;
1576}
1577
1578struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1579 const char *name,
1580 unsigned long align,
1581 unsigned long size)
1582{
1583 int newidx = f->header.e_shnum++;
1584 struct obj_section *sec;
1585
1586 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1587 f->sections[newidx] = sec = arch_new_section();
1588
1589 memset(sec, 0, sizeof(*sec));
1590 sec->header.sh_type = SHT_PROGBITS;
1591 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1592 sec->header.sh_size = size;
1593 sec->header.sh_addralign = align;
1594 sec->name = name;
1595 sec->idx = newidx;
1596 if (size)
1597 sec->contents = xmalloc(size);
1598
1599 sec->load_next = f->load_order;
1600 f->load_order = sec;
1601 if (f->load_order_search_start == &f->load_order)
1602 f->load_order_search_start = &sec->load_next;
1603
1604 return sec;
1605}
1606
1607void *obj_extend_section(struct obj_section *sec, unsigned long more)
1608{
1609 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001610 if (more) {
1611 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1612 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001613 return sec->contents + oldsize;
1614}
1615
1616
1617
1618/* Conditionally add the symbols from the given symbol set to the
1619 new module. */
1620
1621static int
1622add_symbols_from(
1623 struct obj_file *f,
1624 int idx, struct new_module_symbol *syms, size_t nsyms)
1625{
1626 struct new_module_symbol *s;
1627 size_t i;
1628 int used = 0;
1629
1630 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1631
1632 /* Only add symbols that are already marked external. If we
1633 override locals we may cause problems for argument initialization.
1634 We will also create a false dependency on the module. */
1635 struct obj_symbol *sym;
1636
1637 sym = obj_find_symbol(f, (char *) s->name);
1638 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1639 sym = obj_add_symbol(f, (char *) s->name, -1,
1640 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1641 idx, s->value, 0);
1642 /* Did our symbol just get installed? If so, mark the
1643 module as "used". */
1644 if (sym->secidx == idx)
1645 used = 1;
1646 }
1647 }
1648
1649 return used;
1650}
1651
1652static void add_kernel_symbols(struct obj_file *f)
1653{
1654 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001655 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001656
1657 /* Add module symbols first. */
1658
1659 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1660 if (m->nsyms
1661 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1662 m->nsyms)) m->used = 1, ++nused;
1663
1664 n_ext_modules_used = nused;
1665
1666 /* And finally the symbols from the kernel proper. */
1667
1668 if (nksyms)
1669 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1670}
1671
1672static char *get_modinfo_value(struct obj_file *f, const char *key)
1673{
1674 struct obj_section *sec;
1675 char *p, *v, *n, *ep;
1676 size_t klen = strlen(key);
1677
1678 sec = obj_find_section(f, ".modinfo");
1679 if (sec == NULL)
1680 return NULL;
1681 p = sec->contents;
1682 ep = p + sec->header.sh_size;
1683 while (p < ep) {
1684 v = strchr(p, '=');
1685 n = strchr(p, '\0');
1686 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001687 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001688 return v + 1;
1689 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001690 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001691 return n;
1692 }
1693 p = n + 1;
1694 }
1695
1696 return NULL;
1697}
1698
1699
1700/*======================================================================*/
1701/* Functions relating to module loading in pre 2.1 kernels. */
1702
1703static int
1704old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1705{
1706 while (argc > 0) {
1707 char *p, *q;
1708 struct obj_symbol *sym;
1709 int *loc;
1710
1711 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001712 if ((q = strchr(p, '=')) == NULL) {
1713 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001714 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001715 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001716 *q++ = '\0';
1717
1718 sym = obj_find_symbol(f, p);
1719
1720 /* Also check that the parameter was not resolved from the kernel. */
1721 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001722 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001723 return 0;
1724 }
1725
1726 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1727
1728 /* Do C quoting if we begin with a ". */
1729 if (*q == '"') {
1730 char *r, *str;
1731
1732 str = alloca(strlen(q));
1733 for (r = str, q++; *q != '"'; ++q, ++r) {
1734 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001735 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001736 return 0;
1737 } else if (*q == '\\')
1738 switch (*++q) {
1739 case 'a':
1740 *r = '\a';
1741 break;
1742 case 'b':
1743 *r = '\b';
1744 break;
1745 case 'e':
1746 *r = '\033';
1747 break;
1748 case 'f':
1749 *r = '\f';
1750 break;
1751 case 'n':
1752 *r = '\n';
1753 break;
1754 case 'r':
1755 *r = '\r';
1756 break;
1757 case 't':
1758 *r = '\t';
1759 break;
1760
1761 case '0':
1762 case '1':
1763 case '2':
1764 case '3':
1765 case '4':
1766 case '5':
1767 case '6':
1768 case '7':
1769 {
1770 int c = *q - '0';
1771 if (q[1] >= '0' && q[1] <= '7') {
1772 c = (c * 8) + *++q - '0';
1773 if (q[1] >= '0' && q[1] <= '7')
1774 c = (c * 8) + *++q - '0';
1775 }
1776 *r = c;
1777 }
1778 break;
1779
1780 default:
1781 *r = *q;
1782 break;
1783 } else
1784 *r = *q;
1785 }
1786 *r = '\0';
1787 obj_string_patch(f, sym->secidx, sym->value, str);
1788 } else if (*q >= '0' && *q <= '9') {
1789 do
1790 *loc++ = strtoul(q, &q, 0);
1791 while (*q++ == ',');
1792 } else {
1793 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001794 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001795 char *r; /* To search for commas */
1796
1797 /* Break the string with comas */
1798 while ((r = strchr(q, ',')) != (char *) NULL) {
1799 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001800 obj_string_patch(f, sym->secidx, myloc - contents, q);
1801 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001802 q = r;
1803 }
1804
1805 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001806 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001807 }
1808
1809 argc--, argv++;
1810 }
1811
1812 return 1;
1813}
1814
1815#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1816static int old_is_module_checksummed(struct obj_file *f)
1817{
1818 return obj_find_symbol(f, "Using_Versions") != NULL;
1819}
1820/* Get the module's kernel version in the canonical integer form. */
1821
1822static int
1823old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1824{
1825 struct obj_symbol *sym;
1826 char *p, *q;
1827 int a, b, c;
1828
1829 sym = obj_find_symbol(f, "kernel_version");
1830 if (sym == NULL)
1831 return -1;
1832
1833 p = f->sections[sym->secidx]->contents + sym->value;
1834 strncpy(str, p, STRVERSIONLEN);
1835
1836 a = strtoul(p, &p, 10);
1837 if (*p != '.')
1838 return -1;
1839 b = strtoul(p + 1, &p, 10);
1840 if (*p != '.')
1841 return -1;
1842 c = strtoul(p + 1, &q, 10);
1843 if (p + 1 == q)
1844 return -1;
1845
1846 return a << 16 | b << 8 | c;
1847}
1848
1849#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1850
Eric Andersenf5d5e772001-01-24 23:34:48 +00001851#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001852
1853/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1854
Eric Andersen8c185f92000-09-22 00:38:07 +00001855static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001856{
1857 struct old_kernel_sym *ks, *k;
1858 struct new_module_symbol *s;
1859 struct external_module *mod;
1860 int nks, nms, nmod, i;
1861
1862 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001863 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001864 if (nks)
1865 perror_msg("get_kernel_syms: %s", m_name);
1866 else
1867 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001868 return 0;
1869 }
1870
1871 ks = k = xmalloc(nks * sizeof(*ks));
1872
1873 if (get_kernel_syms(ks) != nks) {
1874 perror("inconsistency with get_kernel_syms -- is someone else "
1875 "playing with modules?");
1876 free(ks);
1877 return 0;
1878 }
1879
1880 /* Collect the module information. */
1881
1882 mod = NULL;
1883 nmod = -1;
1884
1885 while (k->name[0] == '#' && k->name[1]) {
1886 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001887
1888 /* Find out how many symbols this module has. */
1889 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1890 continue;
1891 nms = k2 - k - 1;
1892
1893 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1894 mod[nmod].name = k->name + 1;
1895 mod[nmod].addr = k->value;
1896 mod[nmod].used = 0;
1897 mod[nmod].nsyms = nms;
1898 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1899
1900 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1901 s->name = (unsigned long) k->name;
1902 s->value = k->value;
1903 }
1904
1905 k = k2;
1906 }
1907
1908 ext_modules = mod;
1909 n_ext_modules = nmod + 1;
1910
1911 /* Now collect the symbols for the kernel proper. */
1912
1913 if (k->name[0] == '#')
1914 ++k;
1915
1916 nksyms = nms = nks - (k - ks);
1917 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1918
1919 for (i = 0; i < nms; ++i, ++s, ++k) {
1920 s->name = (unsigned long) k->name;
1921 s->value = k->value;
1922 }
1923
1924 return 1;
1925}
1926
1927/* Return the kernel symbol checksum version, or zero if not used. */
1928
1929static int old_is_kernel_checksummed(void)
1930{
1931 /* Using_Versions is the first symbol. */
1932 if (nksyms > 0
1933 && strcmp((char *) ksyms[0].name,
1934 "Using_Versions") == 0) return ksyms[0].value;
1935 else
1936 return 0;
1937}
1938
1939
1940static int old_create_mod_use_count(struct obj_file *f)
1941{
1942 struct obj_section *sec;
1943
1944 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1945 sizeof(long));
1946
1947 obj_add_symbol(f, "mod_use_count_", -1,
1948 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1949 sizeof(long));
1950
1951 return 1;
1952}
1953
1954static int
1955old_init_module(const char *m_name, struct obj_file *f,
1956 unsigned long m_size)
1957{
1958 char *image;
1959 struct old_mod_routines routines;
1960 struct old_symbol_table *symtab;
1961 int ret;
1962
1963 /* Create the symbol table */
1964 {
1965 int nsyms = 0, strsize = 0, total;
1966
1967 /* Size things first... */
1968 if (flag_export) {
1969 int i;
1970 for (i = 0; i < HASH_BUCKETS; ++i) {
1971 struct obj_symbol *sym;
1972 for (sym = f->symtab[i]; sym; sym = sym->next)
1973 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1974 && sym->secidx <= SHN_HIRESERVE)
1975 {
1976 sym->ksymidx = nsyms++;
1977 strsize += strlen(sym->name) + 1;
1978 }
1979 }
1980 }
1981
1982 total = (sizeof(struct old_symbol_table)
1983 + nsyms * sizeof(struct old_module_symbol)
1984 + n_ext_modules_used * sizeof(struct old_module_ref)
1985 + strsize);
1986 symtab = xmalloc(total);
1987 symtab->size = total;
1988 symtab->n_symbols = nsyms;
1989 symtab->n_refs = n_ext_modules_used;
1990
1991 if (flag_export && nsyms) {
1992 struct old_module_symbol *ksym;
1993 char *str;
1994 int i;
1995
1996 ksym = symtab->symbol;
1997 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1998 + n_ext_modules_used * sizeof(struct old_module_ref));
1999
2000 for (i = 0; i < HASH_BUCKETS; ++i) {
2001 struct obj_symbol *sym;
2002 for (sym = f->symtab[i]; sym; sym = sym->next)
2003 if (sym->ksymidx >= 0) {
2004 ksym->addr = obj_symbol_final_value(f, sym);
2005 ksym->name =
2006 (unsigned long) str - (unsigned long) symtab;
2007
Matt Kraai70a78552001-01-04 02:00:17 +00002008 strcpy(str, sym->name);
2009 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002010 ksym++;
2011 }
2012 }
2013 }
2014
2015 if (n_ext_modules_used) {
2016 struct old_module_ref *ref;
2017 int i;
2018
2019 ref = (struct old_module_ref *)
2020 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2021
2022 for (i = 0; i < n_ext_modules; ++i)
2023 if (ext_modules[i].used)
2024 ref++->module = ext_modules[i].addr;
2025 }
2026 }
2027
2028 /* Fill in routines. */
2029
2030 routines.init =
2031 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2032 routines.cleanup =
2033 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2034
2035 /* Whew! All of the initialization is complete. Collect the final
2036 module image and give it to the kernel. */
2037
2038 image = xmalloc(m_size);
2039 obj_create_image(f, image);
2040
2041 /* image holds the complete relocated module, accounting correctly for
2042 mod_use_count. However the old module kernel support assume that
2043 it is receiving something which does not contain mod_use_count. */
2044 ret = old_sys_init_module(m_name, image + sizeof(long),
2045 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2046 : 0), &routines, symtab);
2047 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002048 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002049
2050 free(image);
2051 free(symtab);
2052
2053 return ret == 0;
2054}
2055
2056#else
2057
2058#define old_create_mod_use_count(x) TRUE
2059#define old_init_module(x, y, z) TRUE
2060
Eric Andersenf5d5e772001-01-24 23:34:48 +00002061#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002062
2063
2064
2065/*======================================================================*/
2066/* Functions relating to module loading after 2.1.18. */
2067
2068static int
2069new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2070{
2071 while (argc > 0) {
2072 char *p, *q, *key;
2073 struct obj_symbol *sym;
2074 char *contents, *loc;
2075 int min, max, n;
2076
2077 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002078 if ((q = strchr(p, '=')) == NULL) {
2079 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002080 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002081 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002082
2083 key = alloca(q - p + 6);
2084 memcpy(key, "parm_", 5);
2085 memcpy(key + 5, p, q - p);
2086 key[q - p + 5] = 0;
2087
2088 p = get_modinfo_value(f, key);
2089 key += 5;
2090 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002091 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002092 return 0;
2093 }
2094
2095 sym = obj_find_symbol(f, key);
2096
2097 /* Also check that the parameter was not resolved from the kernel. */
2098 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002099 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002100 return 0;
2101 }
2102
2103 if (isdigit(*p)) {
2104 min = strtoul(p, &p, 10);
2105 if (*p == '-')
2106 max = strtoul(p + 1, &p, 10);
2107 else
2108 max = min;
2109 } else
2110 min = max = 1;
2111
2112 contents = f->sections[sym->secidx]->contents;
2113 loc = contents + sym->value;
2114 n = (*++q != '\0');
2115
2116 while (1) {
2117 if ((*p == 's') || (*p == 'c')) {
2118 char *str;
2119
2120 /* Do C quoting if we begin with a ", else slurp the lot. */
2121 if (*q == '"') {
2122 char *r;
2123
2124 str = alloca(strlen(q));
2125 for (r = str, q++; *q != '"'; ++q, ++r) {
2126 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002127 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002128 key);
2129 return 0;
2130 } else if (*q == '\\')
2131 switch (*++q) {
2132 case 'a':
2133 *r = '\a';
2134 break;
2135 case 'b':
2136 *r = '\b';
2137 break;
2138 case 'e':
2139 *r = '\033';
2140 break;
2141 case 'f':
2142 *r = '\f';
2143 break;
2144 case 'n':
2145 *r = '\n';
2146 break;
2147 case 'r':
2148 *r = '\r';
2149 break;
2150 case 't':
2151 *r = '\t';
2152 break;
2153
2154 case '0':
2155 case '1':
2156 case '2':
2157 case '3':
2158 case '4':
2159 case '5':
2160 case '6':
2161 case '7':
2162 {
2163 int c = *q - '0';
2164 if (q[1] >= '0' && q[1] <= '7') {
2165 c = (c * 8) + *++q - '0';
2166 if (q[1] >= '0' && q[1] <= '7')
2167 c = (c * 8) + *++q - '0';
2168 }
2169 *r = c;
2170 }
2171 break;
2172
2173 default:
2174 *r = *q;
2175 break;
2176 } else
2177 *r = *q;
2178 }
2179 *r = '\0';
2180 ++q;
2181 } else {
2182 char *r;
2183
2184 /* In this case, the string is not quoted. We will break
2185 it using the coma (like for ints). If the user wants to
2186 include comas in a string, he just has to quote it */
2187
2188 /* Search the next coma */
2189 r = strchr(q, ',');
2190
2191 /* Found ? */
2192 if (r != (char *) NULL) {
2193 /* Recopy the current field */
2194 str = alloca(r - q + 1);
2195 memcpy(str, q, r - q);
2196
2197 /* I don't know if it is usefull, as the previous case
2198 doesn't null terminate the string ??? */
2199 str[r - q] = '\0';
2200
2201 /* Keep next fields */
2202 q = r;
2203 } else {
2204 /* last string */
2205 str = q;
2206 q = "";
2207 }
2208 }
2209
2210 if (*p == 's') {
2211 /* Normal string */
2212 obj_string_patch(f, sym->secidx, loc - contents, str);
2213 loc += tgt_sizeof_char_p;
2214 } else {
2215 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002216 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002217
2218 /* Get the size of each member */
2219 /* Probably we should do that outside the loop ? */
2220 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002221 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002222 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002223 return 0;
2224 }
2225 charssize = strtoul(p + 1, (char **) NULL, 10);
2226
2227 /* Check length */
2228 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002229 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002230 charssize - 1);
2231 return 0;
2232 }
2233
2234 /* Copy to location */
2235 strcpy((char *) loc, str);
2236 loc += charssize;
2237 }
2238 } else {
2239 long v = strtoul(q, &q, 0);
2240 switch (*p) {
2241 case 'b':
2242 *loc++ = v;
2243 break;
2244 case 'h':
2245 *(short *) loc = v;
2246 loc += tgt_sizeof_short;
2247 break;
2248 case 'i':
2249 *(int *) loc = v;
2250 loc += tgt_sizeof_int;
2251 break;
2252 case 'l':
2253 *(long *) loc = v;
2254 loc += tgt_sizeof_long;
2255 break;
2256
2257 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002258 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002259 return 0;
2260 }
2261 }
2262
2263 retry_end_of_value:
2264 switch (*q) {
2265 case '\0':
2266 goto end_of_arg;
2267
2268 case ' ':
2269 case '\t':
2270 case '\n':
2271 case '\r':
2272 ++q;
2273 goto retry_end_of_value;
2274
2275 case ',':
2276 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002277 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002278 return 0;
2279 }
2280 ++q;
2281 break;
2282
2283 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002284 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002285 return 0;
2286 }
2287 }
2288
2289 end_of_arg:
2290 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002291 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002292 return 0;
2293 }
2294
2295 argc--, argv++;
2296 }
2297
2298 return 1;
2299}
2300
2301#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2302static int new_is_module_checksummed(struct obj_file *f)
2303{
2304 const char *p = get_modinfo_value(f, "using_checksums");
2305 if (p)
2306 return atoi(p);
2307 else
2308 return 0;
2309}
2310
2311/* Get the module's kernel version in the canonical integer form. */
2312
2313static int
2314new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2315{
2316 char *p, *q;
2317 int a, b, c;
2318
2319 p = get_modinfo_value(f, "kernel_version");
2320 if (p == NULL)
2321 return -1;
2322 strncpy(str, p, STRVERSIONLEN);
2323
2324 a = strtoul(p, &p, 10);
2325 if (*p != '.')
2326 return -1;
2327 b = strtoul(p + 1, &p, 10);
2328 if (*p != '.')
2329 return -1;
2330 c = strtoul(p + 1, &q, 10);
2331 if (p + 1 == q)
2332 return -1;
2333
2334 return a << 16 | b << 8 | c;
2335}
2336
2337#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2338
2339
Eric Andersenf5d5e772001-01-24 23:34:48 +00002340#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002341
2342/* Fetch the loaded modules, and all currently exported symbols. */
2343
2344static int new_get_kernel_symbols(void)
2345{
2346 char *module_names, *mn;
2347 struct external_module *modules, *m;
2348 struct new_module_symbol *syms, *s;
2349 size_t ret, bufsize, nmod, nsyms, i, j;
2350
2351 /* Collect the loaded modules. */
2352
2353 module_names = xmalloc(bufsize = 256);
2354 retry_modules_load:
2355 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002356 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002357 module_names = xrealloc(module_names, bufsize = ret);
2358 goto retry_modules_load;
2359 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002360 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002361 return 0;
2362 }
2363
2364 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002365
2366 /* Collect the modules' symbols. */
2367
Mark Whitley94fd4802001-03-12 23:08:34 +00002368 if (nmod){
2369 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2370 memset(modules, 0, nmod * sizeof(*modules));
2371 for (i = 0, mn = module_names, m = modules;
2372 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2373 struct new_module_info info;
2374
2375 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2376 if (errno == ENOENT) {
2377 /* The module was removed out from underneath us. */
2378 continue;
2379 }
2380 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002381 return 0;
2382 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002383
2384 syms = xmalloc(bufsize = 1024);
2385 retry_mod_sym_load:
2386 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2387 switch (errno) {
2388 case ENOSPC:
2389 syms = xrealloc(syms, bufsize = ret);
2390 goto retry_mod_sym_load;
2391 case ENOENT:
2392 /* The module was removed out from underneath us. */
2393 continue;
2394 default:
2395 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2396 return 0;
2397 }
2398 }
2399 nsyms = ret;
2400
2401 m->name = mn;
2402 m->addr = info.addr;
2403 m->nsyms = nsyms;
2404 m->syms = syms;
2405
2406 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2407 s->name += (unsigned long) syms;
2408 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002409 }
2410 }
2411
2412 /* Collect the kernel's symbols. */
2413
2414 syms = xmalloc(bufsize = 16 * 1024);
2415 retry_kern_sym_load:
2416 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002417 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002418 syms = xrealloc(syms, bufsize = ret);
2419 goto retry_kern_sym_load;
2420 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002421 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002422 return 0;
2423 }
2424 nksyms = nsyms = ret;
2425 ksyms = syms;
2426
2427 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2428 s->name += (unsigned long) syms;
2429 }
2430 return 1;
2431}
2432
2433
2434/* Return the kernel symbol checksum version, or zero if not used. */
2435
2436static int new_is_kernel_checksummed(void)
2437{
2438 struct new_module_symbol *s;
2439 size_t i;
2440
2441 /* Using_Versions is not the first symbol, but it should be in there. */
2442
2443 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2444 if (strcmp((char *) s->name, "Using_Versions") == 0)
2445 return s->value;
2446
2447 return 0;
2448}
2449
2450
2451static int new_create_this_module(struct obj_file *f, const char *m_name)
2452{
2453 struct obj_section *sec;
2454
2455 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2456 sizeof(struct new_module));
2457 memset(sec->contents, 0, sizeof(struct new_module));
2458
2459 obj_add_symbol(f, "__this_module", -1,
2460 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2461 sizeof(struct new_module));
2462
2463 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2464 m_name);
2465
2466 return 1;
2467}
2468
2469
2470static int new_create_module_ksymtab(struct obj_file *f)
2471{
2472 struct obj_section *sec;
2473 int i;
2474
2475 /* We must always add the module references. */
2476
2477 if (n_ext_modules_used) {
2478 struct new_module_ref *dep;
2479 struct obj_symbol *tm;
2480
2481 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2482 (sizeof(struct new_module_ref)
2483 * n_ext_modules_used));
2484 if (!sec)
2485 return 0;
2486
2487 tm = obj_find_symbol(f, "__this_module");
2488 dep = (struct new_module_ref *) sec->contents;
2489 for (i = 0; i < n_ext_modules; ++i)
2490 if (ext_modules[i].used) {
2491 dep->dep = ext_modules[i].addr;
2492 obj_symbol_patch(f, sec->idx,
2493 (char *) &dep->ref - sec->contents, tm);
2494 dep->next_ref = 0;
2495 ++dep;
2496 }
2497 }
2498
2499 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2500 size_t nsyms;
2501 int *loaded;
2502
2503 sec =
2504 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2505 0);
2506
2507 /* We don't want to export symbols residing in sections that
2508 aren't loaded. There are a number of these created so that
2509 we make sure certain module options don't appear twice. */
2510
2511 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2512 while (--i >= 0)
2513 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2514
2515 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2516 struct obj_symbol *sym;
2517 for (sym = f->symtab[i]; sym; sym = sym->next)
2518 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2519 && sym->secidx <= SHN_HIRESERVE
2520 && (sym->secidx >= SHN_LORESERVE
2521 || loaded[sym->secidx])) {
2522 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2523
2524 obj_symbol_patch(f, sec->idx, ofs, sym);
2525 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2526 sym->name);
2527
2528 nsyms++;
2529 }
2530 }
2531
2532 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2533 }
2534
2535 return 1;
2536}
2537
2538
2539static int
2540new_init_module(const char *m_name, struct obj_file *f,
2541 unsigned long m_size)
2542{
2543 struct new_module *module;
2544 struct obj_section *sec;
2545 void *image;
2546 int ret;
2547 tgt_long m_addr;
2548
2549 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002550 if (!sec || !sec->contents) {
2551 perror_msg_and_die("corrupt module %s?",m_name);
2552 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002553 module = (struct new_module *) sec->contents;
2554 m_addr = sec->header.sh_addr;
2555
2556 module->size_of_struct = sizeof(*module);
2557 module->size = m_size;
2558 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2559
2560 sec = obj_find_section(f, "__ksymtab");
2561 if (sec && sec->header.sh_size) {
2562 module->syms = sec->header.sh_addr;
2563 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2564 }
2565
2566 if (n_ext_modules_used) {
2567 sec = obj_find_section(f, ".kmodtab");
2568 module->deps = sec->header.sh_addr;
2569 module->ndeps = n_ext_modules_used;
2570 }
2571
2572 module->init =
2573 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2574 module->cleanup =
2575 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2576
2577 sec = obj_find_section(f, "__ex_table");
2578 if (sec) {
2579 module->ex_table_start = sec->header.sh_addr;
2580 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2581 }
2582
2583 sec = obj_find_section(f, ".text.init");
2584 if (sec) {
2585 module->runsize = sec->header.sh_addr - m_addr;
2586 }
2587 sec = obj_find_section(f, ".data.init");
2588 if (sec) {
2589 if (!module->runsize ||
2590 module->runsize > sec->header.sh_addr - m_addr)
2591 module->runsize = sec->header.sh_addr - m_addr;
2592 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002593 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2594 if (sec && sec->header.sh_size) {
2595 module->archdata_start = (void*)sec->header.sh_addr;
2596 module->archdata_end = module->archdata_start + sec->header.sh_size;
2597 }
2598 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2599 if (sec && sec->header.sh_size) {
2600 module->kallsyms_start = (void*)sec->header.sh_addr;
2601 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2602 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002603
2604 if (!arch_init_module(f, module))
2605 return 0;
2606
2607 /* Whew! All of the initialization is complete. Collect the final
2608 module image and give it to the kernel. */
2609
2610 image = xmalloc(m_size);
2611 obj_create_image(f, image);
2612
Eric Andersen64c8b172001-04-05 07:33:10 +00002613 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002614 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002615 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002616
2617 free(image);
2618
2619 return ret == 0;
2620}
2621
2622#else
2623
2624#define new_init_module(x, y, z) TRUE
2625#define new_create_this_module(x, y) 0
2626#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002627#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002628
Eric Andersenf5d5e772001-01-24 23:34:48 +00002629#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002630
2631
2632/*======================================================================*/
2633
2634int
2635obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2636 const char *string)
2637{
2638 struct obj_string_patch *p;
2639 struct obj_section *strsec;
2640 size_t len = strlen(string) + 1;
2641 char *loc;
2642
2643 p = xmalloc(sizeof(*p));
2644 p->next = f->string_patches;
2645 p->reloc_secidx = secidx;
2646 p->reloc_offset = offset;
2647 f->string_patches = p;
2648
2649 strsec = obj_find_section(f, ".kstrtab");
2650 if (strsec == NULL) {
2651 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2652 p->string_offset = 0;
2653 loc = strsec->contents;
2654 } else {
2655 p->string_offset = strsec->header.sh_size;
2656 loc = obj_extend_section(strsec, len);
2657 }
2658 memcpy(loc, string, len);
2659
2660 return 1;
2661}
2662
2663int
2664obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2665 struct obj_symbol *sym)
2666{
2667 struct obj_symbol_patch *p;
2668
2669 p = xmalloc(sizeof(*p));
2670 p->next = f->symbol_patches;
2671 p->reloc_secidx = secidx;
2672 p->reloc_offset = offset;
2673 p->sym = sym;
2674 f->symbol_patches = p;
2675
2676 return 1;
2677}
2678
2679int obj_check_undefineds(struct obj_file *f)
2680{
2681 unsigned long i;
2682 int ret = 1;
2683
2684 for (i = 0; i < HASH_BUCKETS; ++i) {
2685 struct obj_symbol *sym;
2686 for (sym = f->symtab[i]; sym; sym = sym->next)
2687 if (sym->secidx == SHN_UNDEF) {
2688 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2689 sym->secidx = SHN_ABS;
2690 sym->value = 0;
2691 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002692 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 ret = 0;
2694 }
2695 }
2696 }
2697
2698 return ret;
2699}
2700
2701void obj_allocate_commons(struct obj_file *f)
2702{
2703 struct common_entry {
2704 struct common_entry *next;
2705 struct obj_symbol *sym;
2706 } *common_head = NULL;
2707
2708 unsigned long i;
2709
2710 for (i = 0; i < HASH_BUCKETS; ++i) {
2711 struct obj_symbol *sym;
2712 for (sym = f->symtab[i]; sym; sym = sym->next)
2713 if (sym->secidx == SHN_COMMON) {
2714 /* Collect all COMMON symbols and sort them by size so as to
2715 minimize space wasted by alignment requirements. */
2716 {
2717 struct common_entry **p, *n;
2718 for (p = &common_head; *p; p = &(*p)->next)
2719 if (sym->size <= (*p)->sym->size)
2720 break;
2721
2722 n = alloca(sizeof(*n));
2723 n->next = *p;
2724 n->sym = sym;
2725 *p = n;
2726 }
2727 }
2728 }
2729
2730 for (i = 1; i < f->local_symtab_size; ++i) {
2731 struct obj_symbol *sym = f->local_symtab[i];
2732 if (sym && sym->secidx == SHN_COMMON) {
2733 struct common_entry **p, *n;
2734 for (p = &common_head; *p; p = &(*p)->next)
2735 if (sym == (*p)->sym)
2736 break;
2737 else if (sym->size < (*p)->sym->size) {
2738 n = alloca(sizeof(*n));
2739 n->next = *p;
2740 n->sym = sym;
2741 *p = n;
2742 break;
2743 }
2744 }
2745 }
2746
2747 if (common_head) {
2748 /* Find the bss section. */
2749 for (i = 0; i < f->header.e_shnum; ++i)
2750 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2751 break;
2752
2753 /* If for some reason there hadn't been one, create one. */
2754 if (i == f->header.e_shnum) {
2755 struct obj_section *sec;
2756
2757 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2758 f->sections[i] = sec = arch_new_section();
2759 f->header.e_shnum = i + 1;
2760
2761 memset(sec, 0, sizeof(*sec));
2762 sec->header.sh_type = SHT_PROGBITS;
2763 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2764 sec->name = ".bss";
2765 sec->idx = i;
2766 }
2767
2768 /* Allocate the COMMONS. */
2769 {
2770 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2771 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2772 struct common_entry *c;
2773
2774 for (c = common_head; c; c = c->next) {
2775 ElfW(Addr) align = c->sym->value;
2776
2777 if (align > max_align)
2778 max_align = align;
2779 if (bss_size & (align - 1))
2780 bss_size = (bss_size | (align - 1)) + 1;
2781
2782 c->sym->secidx = i;
2783 c->sym->value = bss_size;
2784
2785 bss_size += c->sym->size;
2786 }
2787
2788 f->sections[i]->header.sh_size = bss_size;
2789 f->sections[i]->header.sh_addralign = max_align;
2790 }
2791 }
2792
2793 /* For the sake of patch relocation and parameter initialization,
2794 allocate zeroed data for NOBITS sections now. Note that after
2795 this we cannot assume NOBITS are really empty. */
2796 for (i = 0; i < f->header.e_shnum; ++i) {
2797 struct obj_section *s = f->sections[i];
2798 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002799 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002800 s->contents = memset(xmalloc(s->header.sh_size),
2801 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002802 else
2803 s->contents = NULL;
2804
Eric Andersen9f16d612000-06-12 23:11:16 +00002805 s->header.sh_type = SHT_PROGBITS;
2806 }
2807 }
2808}
2809
2810unsigned long obj_load_size(struct obj_file *f)
2811{
2812 unsigned long dot = 0;
2813 struct obj_section *sec;
2814
2815 /* Finalize the positions of the sections relative to one another. */
2816
2817 for (sec = f->load_order; sec; sec = sec->load_next) {
2818 ElfW(Addr) align;
2819
2820 align = sec->header.sh_addralign;
2821 if (align && (dot & (align - 1)))
2822 dot = (dot | (align - 1)) + 1;
2823
2824 sec->header.sh_addr = dot;
2825 dot += sec->header.sh_size;
2826 }
2827
2828 return dot;
2829}
2830
2831int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2832{
2833 int i, n = f->header.e_shnum;
2834 int ret = 1;
2835
2836 /* Finalize the addresses of the sections. */
2837
2838 f->baseaddr = base;
2839 for (i = 0; i < n; ++i)
2840 f->sections[i]->header.sh_addr += base;
2841
2842 /* And iterate over all of the relocations. */
2843
2844 for (i = 0; i < n; ++i) {
2845 struct obj_section *relsec, *symsec, *targsec, *strsec;
2846 ElfW(RelM) * rel, *relend;
2847 ElfW(Sym) * symtab;
2848 const char *strtab;
2849
2850 relsec = f->sections[i];
2851 if (relsec->header.sh_type != SHT_RELM)
2852 continue;
2853
2854 symsec = f->sections[relsec->header.sh_link];
2855 targsec = f->sections[relsec->header.sh_info];
2856 strsec = f->sections[symsec->header.sh_link];
2857
2858 rel = (ElfW(RelM) *) relsec->contents;
2859 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2860 symtab = (ElfW(Sym) *) symsec->contents;
2861 strtab = (const char *) strsec->contents;
2862
2863 for (; rel < relend; ++rel) {
2864 ElfW(Addr) value = 0;
2865 struct obj_symbol *intsym = NULL;
2866 unsigned long symndx;
2867 ElfW(Sym) * extsym = 0;
2868 const char *errmsg;
2869
2870 /* Attempt to find a value to use for this relocation. */
2871
2872 symndx = ELFW(R_SYM) (rel->r_info);
2873 if (symndx) {
2874 /* Note we've already checked for undefined symbols. */
2875
2876 extsym = &symtab[symndx];
2877 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2878 /* Local symbols we look up in the local table to be sure
2879 we get the one that is really intended. */
2880 intsym = f->local_symtab[symndx];
2881 } else {
2882 /* Others we look up in the hash table. */
2883 const char *name;
2884 if (extsym->st_name)
2885 name = strtab + extsym->st_name;
2886 else
2887 name = f->sections[extsym->st_shndx]->name;
2888 intsym = obj_find_symbol(f, name);
2889 }
2890
2891 value = obj_symbol_final_value(f, intsym);
2892 intsym->referenced = 1;
2893 }
2894#if SHT_RELM == SHT_RELA
2895#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2896 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2897 if (!extsym || !extsym->st_name ||
2898 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2899#endif
2900 value += rel->r_addend;
2901#endif
2902
2903 /* Do it! */
2904 switch (arch_apply_relocation
2905 (f, targsec, symsec, intsym, rel, value)) {
2906 case obj_reloc_ok:
2907 break;
2908
2909 case obj_reloc_overflow:
2910 errmsg = "Relocation overflow";
2911 goto bad_reloc;
2912 case obj_reloc_dangerous:
2913 errmsg = "Dangerous relocation";
2914 goto bad_reloc;
2915 case obj_reloc_unhandled:
2916 errmsg = "Unhandled relocation";
2917 bad_reloc:
2918 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002919 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002920 (long) ELFW(R_TYPE) (rel->r_info),
2921 strtab + extsym->st_name);
2922 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002923 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002924 (long) ELFW(R_TYPE) (rel->r_info));
2925 }
2926 ret = 0;
2927 break;
2928 }
2929 }
2930 }
2931
2932 /* Finally, take care of the patches. */
2933
2934 if (f->string_patches) {
2935 struct obj_string_patch *p;
2936 struct obj_section *strsec;
2937 ElfW(Addr) strsec_base;
2938 strsec = obj_find_section(f, ".kstrtab");
2939 strsec_base = strsec->header.sh_addr;
2940
2941 for (p = f->string_patches; p; p = p->next) {
2942 struct obj_section *targsec = f->sections[p->reloc_secidx];
2943 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2944 = strsec_base + p->string_offset;
2945 }
2946 }
2947
2948 if (f->symbol_patches) {
2949 struct obj_symbol_patch *p;
2950
2951 for (p = f->symbol_patches; p; p = p->next) {
2952 struct obj_section *targsec = f->sections[p->reloc_secidx];
2953 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2954 = obj_symbol_final_value(f, p->sym);
2955 }
2956 }
2957
2958 return ret;
2959}
2960
2961int obj_create_image(struct obj_file *f, char *image)
2962{
2963 struct obj_section *sec;
2964 ElfW(Addr) base = f->baseaddr;
2965
2966 for (sec = f->load_order; sec; sec = sec->load_next) {
2967 char *secimg;
2968
Eric Andersen2bf658d2001-02-24 20:01:53 +00002969 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002970 continue;
2971
2972 secimg = image + (sec->header.sh_addr - base);
2973
2974 /* Note that we allocated data for NOBITS sections earlier. */
2975 memcpy(secimg, sec->contents, sec->header.sh_size);
2976 }
2977
2978 return 1;
2979}
2980
2981/*======================================================================*/
2982
Eric Andersen8ae319a2001-05-21 16:09:18 +00002983struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002984{
2985 struct obj_file *f;
2986 ElfW(Shdr) * section_headers;
2987 int shnum, i;
2988 char *shstrtab;
2989
2990 /* Read the file header. */
2991
2992 f = arch_new_file();
2993 memset(f, 0, sizeof(*f));
2994 f->symbol_cmp = strcmp;
2995 f->symbol_hash = obj_elf_hash;
2996 f->load_order_search_start = &f->load_order;
2997
2998 fseek(fp, 0, SEEK_SET);
2999 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003000 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003001 return NULL;
3002 }
3003
3004 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3005 || f->header.e_ident[EI_MAG1] != ELFMAG1
3006 || f->header.e_ident[EI_MAG2] != ELFMAG2
3007 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003008 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003009 return NULL;
3010 }
3011 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3012 || f->header.e_ident[EI_DATA] != ELFDATAM
3013 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3014 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003015 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003016 return NULL;
3017 }
3018 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003019 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003020 return NULL;
3021 }
3022
3023 /* Read the section headers. */
3024
3025 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003026 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003027 (unsigned long) f->header.e_shentsize,
3028 (unsigned long) sizeof(ElfW(Shdr)));
3029 return NULL;
3030 }
3031
3032 shnum = f->header.e_shnum;
3033 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3034 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3035
3036 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3037 fseek(fp, f->header.e_shoff, SEEK_SET);
3038 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003039 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003040 return NULL;
3041 }
3042
3043 /* Read the section data. */
3044
3045 for (i = 0; i < shnum; ++i) {
3046 struct obj_section *sec;
3047
3048 f->sections[i] = sec = arch_new_section();
3049 memset(sec, 0, sizeof(*sec));
3050
3051 sec->header = section_headers[i];
3052 sec->idx = i;
3053
Eric Andersen2bf658d2001-02-24 20:01:53 +00003054 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003055 case SHT_NULL:
3056 case SHT_NOTE:
3057 case SHT_NOBITS:
3058 /* ignore */
3059 break;
3060
3061 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003062#if LOADBITS
3063 if (!loadprogbits) {
3064 sec->contents = NULL;
3065 break;
3066 }
3067#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003068 case SHT_SYMTAB:
3069 case SHT_STRTAB:
3070 case SHT_RELM:
3071 if (sec->header.sh_size > 0) {
3072 sec->contents = xmalloc(sec->header.sh_size);
3073 fseek(fp, sec->header.sh_offset, SEEK_SET);
3074 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003075 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003076 return NULL;
3077 }
3078 } else {
3079 sec->contents = NULL;
3080 }
3081 break;
3082
3083#if SHT_RELM == SHT_REL
3084 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003085 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003086 return NULL;
3087#else
3088 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003089 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003090 return NULL;
3091#endif
3092
3093 default:
3094 if (sec->header.sh_type >= SHT_LOPROC) {
3095 /* Assume processor specific section types are debug
3096 info and can safely be ignored. If this is ever not
3097 the case (Hello MIPS?), don't put ifdefs here but
3098 create an arch_load_proc_section(). */
3099 break;
3100 }
3101
Matt Kraaidd19c692001-01-31 19:00:21 +00003102 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003103 (long) sec->header.sh_type);
3104 return NULL;
3105 }
3106 }
3107
3108 /* Do what sort of interpretation as needed by each section. */
3109
3110 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3111
3112 for (i = 0; i < shnum; ++i) {
3113 struct obj_section *sec = f->sections[i];
3114 sec->name = shstrtab + sec->header.sh_name;
3115 }
3116
3117 for (i = 0; i < shnum; ++i) {
3118 struct obj_section *sec = f->sections[i];
3119
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003120 /* .modinfo should be contents only but gcc has no attribute for that.
3121 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3122 */
3123 if (strcmp(sec->name, ".modinfo") == 0)
3124 sec->header.sh_flags &= ~SHF_ALLOC;
3125
Eric Andersen9f16d612000-06-12 23:11:16 +00003126 if (sec->header.sh_flags & SHF_ALLOC)
3127 obj_insert_section_load_order(f, sec);
3128
3129 switch (sec->header.sh_type) {
3130 case SHT_SYMTAB:
3131 {
3132 unsigned long nsym, j;
3133 char *strtab;
3134 ElfW(Sym) * sym;
3135
3136 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003137 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003138 (unsigned long) sec->header.sh_entsize,
3139 (unsigned long) sizeof(ElfW(Sym)));
3140 return NULL;
3141 }
3142
3143 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3144 strtab = f->sections[sec->header.sh_link]->contents;
3145 sym = (ElfW(Sym) *) sec->contents;
3146
3147 /* Allocate space for a table of local symbols. */
3148 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003149 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003150
3151 /* Insert all symbols into the hash table. */
3152 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3153 const char *name;
3154 if (sym->st_name)
3155 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003156 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003157 name = f->sections[sym->st_shndx]->name;
3158
3159 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3160 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003161 }
3162 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003163 break;
3164
3165 case SHT_RELM:
3166 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003167 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003168 (unsigned long) sec->header.sh_entsize,
3169 (unsigned long) sizeof(ElfW(RelM)));
3170 return NULL;
3171 }
3172 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003173 /* XXX Relocation code from modutils-2.3.19 is not here.
3174 * Why? That's about 20 lines of code from obj/obj_load.c,
3175 * which gets done in a second pass through the sections.
3176 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003177 }
3178 }
3179
3180 return f;
3181}
3182
Eric Andersen8ae319a2001-05-21 16:09:18 +00003183#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3184/*
3185 * load the unloaded sections directly into the memory allocated by
3186 * kernel for the module
3187 */
3188
3189int obj_load_progbits(FILE * fp, struct obj_file* f)
3190{
3191 char* imagebase = (char*) f->imagebase;
3192 ElfW(Addr) base = f->baseaddr;
3193 struct obj_section* sec;
3194
3195 for (sec = f->load_order; sec; sec = sec->load_next) {
3196
3197 /* section already loaded? */
3198 if (sec->contents != NULL)
3199 continue;
3200
3201 if (sec->header.sh_size == 0)
3202 continue;
3203
3204 sec->contents = imagebase + (sec->header.sh_addr - base);
3205 fseek(fp, sec->header.sh_offset, SEEK_SET);
3206 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3207 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3208 return 0;
3209 }
3210
3211 }
3212 return 1;
3213}
3214#endif
3215
Eric Andersen9f16d612000-06-12 23:11:16 +00003216static void hide_special_symbols(struct obj_file *f)
3217{
3218 static const char *const specials[] = {
3219 "cleanup_module",
3220 "init_module",
3221 "kernel_version",
3222 NULL
3223 };
3224
3225 struct obj_symbol *sym;
3226 const char *const *p;
3227
3228 for (p = specials; *p; ++p)
3229 if ((sym = obj_find_symbol(f, *p)) != NULL)
3230 sym->info =
3231 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3232}
3233
3234
3235
3236extern int insmod_main( int argc, char **argv)
3237{
Eric Andersena18aaf12001-01-24 19:07:09 +00003238 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003239 int k_crcs;
3240 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003241 int len;
3242 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003243 unsigned long m_size;
3244 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003245 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003246 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003247 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003248 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003249 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 int m_has_modinfo;
3251#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3252 int k_version;
3253 char k_strversion[STRVERSIONLEN];
3254 char m_strversion[STRVERSIONLEN];
3255 int m_version;
3256 int m_crcs;
3257#endif
3258
Erik Andersene49d5ec2000-02-08 19:58:47 +00003259 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003260 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003261 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003262 case 'f': /* force loading */
3263 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003264 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003265 case 'k': /* module loaded by kerneld, auto-cleanable */
3266 flag_autoclean = 1;
3267 break;
3268 case 'v': /* verbose output */
3269 flag_verbose = 1;
3270 break;
3271 case 'x': /* do not export externs */
3272 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003273 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003274 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003275 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003276 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003277 case 'L': /* Stub warning */
3278 /* This is needed for compatibility with modprobe.
3279 * In theory, this does locking, but we don't do
3280 * that. So be careful and plan your life around not
3281 * loading the same module 50 times concurrently. */
3282 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003283 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003284 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003285 }
Erik Andersend387d011999-12-21 02:55:11 +00003286 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003287
3288 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003289 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003290 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003291
Erik Andersene49d5ec2000-02-08 19:58:47 +00003292 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003293 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003294 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003295 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003296 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003297 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003298 len = strlen(tmp);
3299
3300 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3301 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003302 memcpy(m_fullName, tmp, len);
3303 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003304 if (*m_name == '\0') {
3305 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003306 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003307 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003308
Eric Andersen14d35432001-05-14 17:07:32 +00003309 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003310 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3311 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003312 struct utsname myuname;
3313
3314 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3315 * but do not error out yet if we fail to find it... */
3316 if (uname(&myuname) == 0) {
3317 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003318 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003319 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3320 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003321 /* Jump through hoops in case /lib/modules/`uname -r`
3322 * is a symlink. We do not want recursive_action to
3323 * follow symlinks, but we do want to follow the
3324 * /lib/modules/`uname -r` dir, So resolve it ourselves
3325 * if it is a link... */
3326 if (realpath (module_dir, real_module_dir) == NULL)
3327 strcpy(real_module_dir, module_dir);
3328 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003329 check_module_name_match, 0, m_fullName);
3330 }
3331
3332 /* Check if we have found anything yet */
3333 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003334 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003335 char module_dir[FILENAME_MAX];
3336 if (realpath (_PATH_MODULES, module_dir) == NULL)
3337 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003338 /* No module found under /lib/modules/`uname -r`, this
3339 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003340 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003341 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003342 {
Eric Andersen14d35432001-05-14 17:07:32 +00003343 if (m_filename[0] == '\0'
3344 || ((fp = fopen(m_filename, "r")) == NULL))
3345 {
3346 error_msg("%s: no module by that name found", m_fullName);
3347 return EXIT_FAILURE;
3348 }
3349 } else
3350 error_msg_and_die("%s: no module by that name found", m_fullName);
3351 }
3352 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003353 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003354
Eric Andersen14d35432001-05-14 17:07:32 +00003355 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003356
Eric Andersen8ae319a2001-05-21 16:09:18 +00003357 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003358 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003359
Eric Andersen9f16d612000-06-12 23:11:16 +00003360 if (get_modinfo_value(f, "kernel_version") == NULL)
3361 m_has_modinfo = 0;
3362 else
3363 m_has_modinfo = 1;
3364
3365#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3366 /* Version correspondence? */
3367
3368 k_version = get_kernel_version(k_strversion);
3369 if (m_has_modinfo) {
3370 m_version = new_get_module_version(f, m_strversion);
3371 } else {
3372 m_version = old_get_module_version(f, m_strversion);
3373 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003374 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003375 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003376 goto out;
3377 }
3378 }
3379
3380 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3381 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003382 error_msg("Warning: 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 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003387 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003389 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003390 m_filename, m_strversion, k_strversion);
3391 goto out;
3392 }
3393 }
3394 k_crcs = 0;
3395#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3396
3397 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3398
3399 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003400#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003401 if (!new_get_kernel_symbols())
3402 goto out;
3403 k_crcs = new_is_kernel_checksummed();
3404#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003405 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003406 goto out;
3407#endif
3408 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003409#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003410 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003411 goto out;
3412 k_crcs = old_is_kernel_checksummed();
3413#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003414 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003415 goto out;
3416#endif
3417 }
3418
3419#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3420 if (m_has_modinfo)
3421 m_crcs = new_is_module_checksummed(f);
3422 else
3423 m_crcs = old_is_module_checksummed(f);
3424
3425 if (m_crcs != k_crcs)
3426 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3427#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3428
Erik Andersene49d5ec2000-02-08 19:58:47 +00003429 /* Let the module know about the kernel symbols. */
3430 add_kernel_symbols(f);
3431
Eric Andersen9f16d612000-06-12 23:11:16 +00003432 /* Allocate common symbols, symbol tables, and string tables. */
3433
3434 if (k_new_syscalls
3435 ? !new_create_this_module(f, m_name)
3436 : !old_create_mod_use_count(f))
3437 {
3438 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003439 }
3440
Eric Andersen9f16d612000-06-12 23:11:16 +00003441 if (!obj_check_undefineds(f)) {
3442 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003443 }
3444 obj_allocate_commons(f);
3445
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003446 /* done with the module name, on to the optional var=value arguments */
3447 ++optind;
3448
Eric Andersen9f16d612000-06-12 23:11:16 +00003449 if (optind < argc) {
3450 if (m_has_modinfo
3451 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3452 : !old_process_module_arguments(f, argc - optind, argv + optind))
3453 {
3454 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003455 }
3456 }
3457
Eric Andersen9f16d612000-06-12 23:11:16 +00003458 arch_create_got(f);
3459 hide_special_symbols(f);
3460
3461 if (k_new_syscalls)
3462 new_create_module_ksymtab(f);
3463
Erik Andersene49d5ec2000-02-08 19:58:47 +00003464 /* Find current size of the module */
3465 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003466
3467
Erik Andersene49d5ec2000-02-08 19:58:47 +00003468 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003469 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003470 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003471 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003472 goto out;
3473 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003474 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003475 m_size);
3476 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003477 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003478 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003479 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003480 }
Erik Andersend387d011999-12-21 02:55:11 +00003481
Eric Andersen8ae319a2001-05-21 16:09:18 +00003482#if !LOADBITS
3483 /*
3484 * the PROGBITS section was not loaded by the obj_load
3485 * now we can load them directly into the kernel memory
3486 */
3487 // f->imagebase = (char*) m_addr;
3488 f->imagebase = (ElfW(Addr)) m_addr;
3489 if (!obj_load_progbits(fp, f)) {
3490 delete_module(m_name);
3491 goto out;
3492 }
3493#endif
3494
Eric Andersen9f16d612000-06-12 23:11:16 +00003495 if (!obj_relocate(f, m_addr)) {
3496 delete_module(m_name);
3497 goto out;
3498 }
Erik Andersend387d011999-12-21 02:55:11 +00003499
Eric Andersen9f16d612000-06-12 23:11:16 +00003500 if (k_new_syscalls
3501 ? !new_init_module(m_name, f, m_size)
3502 : !old_init_module(m_name, f, m_size))
3503 {
3504 delete_module(m_name);
3505 goto out;
3506 }
3507
Matt Kraai3e856ce2000-12-01 02:55:13 +00003508 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003509
3510out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003511 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003512 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003513}