blob: b457fa81cef226792b09e8fec39e56078c142176 [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 Andersen044228d2001-07-17 01:12:36 +0000133#ident "$Id: insmod.c,v 1.68 2001/07/17 01:12:36 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 Andersen044228d2001-07-17 01:12:36 +0000350#ident "$Id: insmod.c,v 1.68 2001/07/17 01:12:36 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
Eric Andersen044228d2001-07-17 01:12:36 +0000540static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000541
Eric Andersen044228d2001-07-17 01:12:36 +0000542static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000543
Eric Andersen044228d2001-07-17 01:12:36 +0000544static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000545 const char *name);
546
Eric Andersen044228d2001-07-17 01:12:36 +0000547static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000548 struct obj_symbol *sym);
549
Eric Andersen044228d2001-07-17 01:12:36 +0000550static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000551 int (*cmp)(const char *, const char *),
552 unsigned long (*hash)(const char *));
553
Eric Andersen044228d2001-07-17 01:12:36 +0000554static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000555 const char *name);
556
Eric Andersen044228d2001-07-17 01:12:36 +0000557static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000558 struct obj_section *sec);
559
Eric Andersen044228d2001-07-17 01:12:36 +0000560static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000561 const char *name,
562 unsigned long align,
563 unsigned long size);
564
Eric Andersen044228d2001-07-17 01:12:36 +0000565static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000566 const char *name,
567 unsigned long align,
568 unsigned long size);
569
Eric Andersen044228d2001-07-17 01:12:36 +0000570static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000571
Eric Andersen044228d2001-07-17 01:12:36 +0000572static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000573 const char *string);
574
Eric Andersen044228d2001-07-17 01:12:36 +0000575static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000576 struct obj_symbol *sym);
577
Eric Andersen044228d2001-07-17 01:12:36 +0000578static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000579
Eric Andersen044228d2001-07-17 01:12:36 +0000580static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000581
Eric Andersen044228d2001-07-17 01:12:36 +0000582static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000583
Eric Andersen044228d2001-07-17 01:12:36 +0000584static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000585
Eric Andersen044228d2001-07-17 01:12:36 +0000586static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000587
Eric Andersen044228d2001-07-17 01:12:36 +0000588static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000589
590/* Architecture specific manipulation routines. */
591
Eric Andersen044228d2001-07-17 01:12:36 +0000592static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000593
Eric Andersen044228d2001-07-17 01:12:36 +0000594static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000595
Eric Andersen044228d2001-07-17 01:12:36 +0000596static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000597
Eric Andersen044228d2001-07-17 01:12:36 +0000598static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000599 struct obj_section *targsec,
600 struct obj_section *symsec,
601 struct obj_symbol *sym,
602 ElfW(RelM) *rel, ElfW(Addr) value);
603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static int arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000605
Eric Andersen044228d2001-07-17 01:12:36 +0000606static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000607
608#endif /* obj.h */
609//----------------------------------------------------------------------------
610//--------end of modutils obj.h
611//----------------------------------------------------------------------------
612
613
614
615
Erik Andersen02104321999-12-17 18:57:34 +0000616
Erik Andersend387d011999-12-21 02:55:11 +0000617#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000618static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000619
Eric Andersen9f16d612000-06-12 23:11:16 +0000620/*======================================================================*/
621
Eric Andersen044228d2001-07-17 01:12:36 +0000622static int flag_force_load = 0;
623static int flag_autoclean = 0;
624static int flag_verbose = 0;
625static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
627
628/*======================================================================*/
629
Eric Andersenfe4208f2000-09-24 03:44:29 +0000630/* previously, these were named i386_* but since we could be
631 compiling for the sh, I've renamed them to the more general
632 arch_* These structures are the same between the x86 and SH,
633 and we can't support anything else right now anyway. In the
634 future maybe they should be #if defined'd */
635
Eric Andersen21adca72000-12-06 18:18:26 +0000636/* Done ;-) */
637
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000638
639
640#if defined(BB_USE_PLT_ENTRIES)
641struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000642{
643 int offset;
644 int allocated:1;
645 int inited:1; /* has been set up */
646};
647#endif
648
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000649#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000650struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000651 int offset;
652 unsigned offset_done:1;
653 unsigned reloc_done:1;
654};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000655#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen2bf658d2001-02-24 20:01:53 +0000657#if defined(__mips__)
658struct mips_hi16
659{
660 struct mips_hi16 *next;
661 Elf32_Addr *addr;
662 Elf32_Addr value;
663};
664#endif
665
Eric Andersenfe4208f2000-09-24 03:44:29 +0000666struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000667 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000668#if defined(BB_USE_PLT_ENTRIES)
669 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000670#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000671#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000672 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000673#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000674#if defined(__mips__)
675 struct mips_hi16 *mips_hi16_list;
676#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000677};
678
Eric Andersenfe4208f2000-09-24 03:44:29 +0000679struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000680 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000681#if defined(BB_USE_PLT_ENTRIES)
682 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000683#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000684#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000685 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000686#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000687};
688
689
Eric Andersen9f16d612000-06-12 23:11:16 +0000690struct external_module {
691 const char *name;
692 ElfW(Addr) addr;
693 int used;
694 size_t nsyms;
695 struct new_module_symbol *syms;
696};
697
Eric Andersen044228d2001-07-17 01:12:36 +0000698static struct new_module_symbol *ksyms;
699static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000700
Eric Andersen044228d2001-07-17 01:12:36 +0000701static struct external_module *ext_modules;
702static int n_ext_modules;
703static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000704extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000705
Eric Andersen14d35432001-05-14 17:07:32 +0000706static char m_filename[FILENAME_MAX + 1];
707static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000708
Eric Andersenfe4208f2000-09-24 03:44:29 +0000709
Erik Andersen02104321999-12-17 18:57:34 +0000710
Eric Andersen9f16d612000-06-12 23:11:16 +0000711/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000712
Eric Andersen9f16d612000-06-12 23:11:16 +0000713
Eric Andersen14d35432001-05-14 17:07:32 +0000714static int check_module_name_match(const char *filename, struct stat *statbuf,
715 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000716{
Eric Andersen14d35432001-05-14 17:07:32 +0000717 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000718
Eric Andersen14d35432001-05-14 17:07:32 +0000719 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000720 return (FALSE);
721 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000722 char *tmp, *tmp1 = strdup(filename);
723 tmp = get_last_path_component(tmp1);
724 if (strcmp(tmp, fullname) == 0) {
725 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000726 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000727 safe_strncpy(m_filename, filename, sizeof(m_filename));
728 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000729 }
Eric Andersen14d35432001-05-14 17:07:32 +0000730 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000731 }
Eric Andersen14d35432001-05-14 17:07:32 +0000732 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000733}
734
Erik Andersen02104321999-12-17 18:57:34 +0000735
Eric Andersen9f16d612000-06-12 23:11:16 +0000736/*======================================================================*/
737
Eric Andersen044228d2001-07-17 01:12:36 +0000738static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000739{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000740 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000741 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000742
743#if defined(BB_USE_PLT_ENTRIES)
744 f->plt = NULL;
745#endif
746#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000747 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000748#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000749#if defined(__mips__)
750 f->mips_hi16_list = NULL;
751#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000752
Eric Andersen9f16d612000-06-12 23:11:16 +0000753 return &f->root;
754}
755
Eric Andersen044228d2001-07-17 01:12:36 +0000756static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000757{
758 return xmalloc(sizeof(struct obj_section));
759}
760
Eric Andersen044228d2001-07-17 01:12:36 +0000761static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000762{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000763 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000764 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000765
766#if defined(BB_USE_PLT_ENTRIES)
767 memset(&sym->pltent, 0, sizeof(sym->pltent));
768#endif
769#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000770 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000771#endif
772
Eric Andersen9f16d612000-06-12 23:11:16 +0000773 return &sym->root;
774}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775
Eric Andersen044228d2001-07-17 01:12:36 +0000776static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000777arch_apply_relocation(struct obj_file *f,
778 struct obj_section *targsec,
779 struct obj_section *symsec,
780 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000781 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000782{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000783 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000784#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000785 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000786#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000787
Eric Andersen21adca72000-12-06 18:18:26 +0000788 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
789 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000790#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000791 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000792#endif
793#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000794 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000795 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000796 unsigned long *ip;
797#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000798 enum obj_reloc ret = obj_reloc_ok;
799
800 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000801
802/* even though these constants seem to be the same for
803 the i386 and the sh, we "#if define" them for clarity
804 and in case that ever changes */
805#if defined(__sh__)
806 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000807#elif defined(__arm__)
808 case R_ARM_NONE:
809#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000810 case R_386_NONE:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000811#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000812 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000813#elif defined(__powerpc__)
814 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000815#elif defined(__mips__)
816 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000817#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000818 break;
819
Eric Andersenfe4208f2000-09-24 03:44:29 +0000820#if defined(__sh__)
821 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000822#elif defined(__arm__)
823 case R_ARM_ABS32:
824#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000825 case R_386_32:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000826#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000827 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828#elif defined(__powerpc__)
829 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000830#elif defined(__mips__)
831 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000832#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 *loc += v;
834 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000835#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000836 case R_68K_8:
837 if (v > 0xff)
838 ret = obj_reloc_overflow;
839 *(char *)loc = v;
840 break;
841 case R_68K_16:
842 if (v > 0xffff)
843 ret = obj_reloc_overflow;
844 *(short *)loc = v;
845 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000846#endif /* __mc68000__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000847
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000848#if defined(__powerpc__)
849 case R_PPC_ADDR16_HA:
850 *(unsigned short *)loc = (v + 0x8000) >> 16;
851 break;
852
853 case R_PPC_ADDR16_HI:
854 *(unsigned short *)loc = v >> 16;
855 break;
856
857 case R_PPC_ADDR16_LO:
858 *(unsigned short *)loc = v;
859 break;
860#endif
861
Eric Andersen2bf658d2001-02-24 20:01:53 +0000862#if defined(__mips__)
863 case R_MIPS_26:
864 if (v % 4)
865 ret = obj_reloc_dangerous;
866 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
867 ret = obj_reloc_overflow;
868 *loc =
869 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
870 0x03ffffff);
871 break;
872
873 case R_MIPS_HI16:
874 {
875 struct mips_hi16 *n;
876
877 /* We cannot relocate this one now because we don't know the value
878 of the carry we need to add. Save the information, and let LO16
879 do the actual relocation. */
880 n = (struct mips_hi16 *) xmalloc(sizeof *n);
881 n->addr = loc;
882 n->value = v;
883 n->next = ifile->mips_hi16_list;
884 ifile->mips_hi16_list = n;
885 break;
886 }
887
888 case R_MIPS_LO16:
889 {
890 unsigned long insnlo = *loc;
891 Elf32_Addr val, vallo;
892
893 /* Sign extend the addend we extract from the lo insn. */
894 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
895
896 if (ifile->mips_hi16_list != NULL) {
897 struct mips_hi16 *l;
898
899 l = ifile->mips_hi16_list;
900 while (l != NULL) {
901 struct mips_hi16 *next;
902 unsigned long insn;
903
904 /* The value for the HI16 had best be the same. */
905 assert(v == l->value);
906
907 /* Do the HI16 relocation. Note that we actually don't
908 need to know anything about the LO16 itself, except where
909 to find the low 16 bits of the addend needed by the LO16. */
910 insn = *l->addr;
911 val =
912 ((insn & 0xffff) << 16) +
913 vallo;
914 val += v;
915
916 /* Account for the sign extension that will happen in the
917 low bits. */
918 val =
919 ((val >> 16) +
920 ((val & 0x8000) !=
921 0)) & 0xffff;
922
923 insn = (insn & ~0xffff) | val;
924 *l->addr = insn;
925
926 next = l->next;
927 free(l);
928 l = next;
929 }
930
931 ifile->mips_hi16_list = NULL;
932 }
933
934 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
935 val = v + vallo;
936 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
937 *loc = insnlo;
938 break;
939 }
940#endif
941
Eric Andersen21adca72000-12-06 18:18:26 +0000942#if defined(__arm__)
943#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000944 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000945 *loc += v - dot;
946 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000947#elif defined(__i386__)
948 case R_386_PLT32:
949 case R_386_PC32:
950 *loc += v - dot;
951 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000952#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000953 case R_68K_PC8:
954 v -= dot;
955 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
956 ret = obj_reloc_overflow;
957 *(char *)loc = v;
958 break;
959 case R_68K_PC16:
960 v -= dot;
961 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
962 ret = obj_reloc_overflow;
963 *(short *)loc = v;
964 break;
965 case R_68K_PC32:
966 *(int *)loc = v - dot;
967 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000968#elif defined(__powerpc__)
969 case R_PPC_REL32:
970 *loc = v - dot;
971 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000972#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000973
Eric Andersenfe4208f2000-09-24 03:44:29 +0000974#if defined(__sh__)
975 case R_SH_PLT32:
976 *loc = v - dot;
977 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000978#elif defined(__i386__)
979#endif
980
981#if defined(BB_USE_PLT_ENTRIES)
982
983#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000984 case R_ARM_PC24:
985 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000986#endif
987#if defined(__powerpc__)
988 case R_PPC_REL24:
989#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000990 /* find the plt entry and initialize it if necessary */
991 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000992
993 pe = (struct arch_plt_entry*) &isym->pltent;
994
Eric Andersen21adca72000-12-06 18:18:26 +0000995 if (! pe->inited) {
996 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000997
998 /* generate some machine code */
999
1000#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001001 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1002 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001003#endif
1004#if defined(__powerpc__)
1005 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1006 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1007 ip[2] = 0x7d6903a6; /* mtctr r11 */
1008 ip[3] = 0x4e800420; /* bctr */
1009#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001010 pe->inited = 1;
1011 }
1012
1013 /* relative distance to target */
1014 v -= dot;
1015 /* if the target is too far away.... */
1016 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1017 /* go via the plt */
1018 v = plt + pe->offset - dot;
1019 }
1020 if (v & 3)
1021 ret = obj_reloc_dangerous;
1022
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001023 /* merge the offset into the instruction. */
1024#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001025 /* Convert to words. */
1026 v >>= 2;
1027
Eric Andersen21adca72000-12-06 18:18:26 +00001028 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001029#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001030#if defined(__powerpc__)
1031 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1032#endif
1033 break;
1034#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001035
Eric Andersen21adca72000-12-06 18:18:26 +00001036#if defined(__arm__)
1037#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001038 case R_SH_GLOB_DAT:
1039 case R_SH_JMP_SLOT:
1040 *loc = v;
1041 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001042#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001043 case R_386_GLOB_DAT:
1044 case R_386_JMP_SLOT:
1045 *loc = v;
1046 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001047#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001048 case R_68K_GLOB_DAT:
1049 case R_68K_JMP_SLOT:
1050 *loc = v;
1051 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001052#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001053
Eric Andersen21adca72000-12-06 18:18:26 +00001054#if defined(__arm__)
1055#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001056 case R_SH_RELATIVE:
1057 *loc += f->baseaddr + rel->r_addend;
1058 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001059#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001060 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001061 *loc += f->baseaddr;
1062 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001063#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001064 case R_68K_RELATIVE:
1065 *(int *)loc += f->baseaddr;
1066 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001067#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001068
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001069#if defined(BB_USE_GOT_ENTRIES)
1070
Eric Andersen8ae319a2001-05-21 16:09:18 +00001071#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001072#if defined(__sh__)
1073 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001074#elif defined(__arm__)
1075 case R_ARM_GOTPC:
1076#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001077 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001078#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001079 assert(got != 0);
1080#if defined(__sh__)
1081 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001082#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001083 *loc += got - dot;
1084#endif
1085 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001086#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001087
Eric Andersenfe4208f2000-09-24 03:44:29 +00001088#if defined(__sh__)
1089 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001090#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001091 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001092#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001093 case R_386_GOT32:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001094#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001095 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001096#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001097 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001098 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001099 if (!isym->gotent.reloc_done) {
1100 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001101 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001102 }
Eric Andersen21adca72000-12-06 18:18:26 +00001103 /* make the reloc with_respect_to_.got */
1104#if defined(__sh__)
1105 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001106#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001107 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001108#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001109 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001110
Eric Andersen21adca72000-12-06 18:18:26 +00001111 /* address relative to the got */
Eric Andersenb4a26e62001-06-19 15:00:52 +00001112#if !defined(__mc68000__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001113#if defined(__sh__)
1114 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001115#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001116 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001117#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001118 case R_386_GOTOFF:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001119#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001120 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001121#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001122 assert(got != 0);
1123 *loc += v - got;
1124 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001125#endif // __mc68000__
Eric Andersen9f16d612000-06-12 23:11:16 +00001126
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001127#endif /* BB_USE_GOT_ENTRIES */
1128
Eric Andersen9f16d612000-06-12 23:11:16 +00001129 default:
Eric Andersen21125542000-12-13 16:41:29 +00001130 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001131 ret = obj_reloc_unhandled;
1132 break;
1133 }
1134
1135 return ret;
1136}
1137
Eric Andersen044228d2001-07-17 01:12:36 +00001138static int arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001139{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001140#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001141 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001142 int i;
1143#if defined(BB_USE_GOT_ENTRIES)
1144 int got_offset = 0, gotneeded = 0;
1145#endif
1146#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001147 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001148#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001149 struct obj_section *relsec, *symsec, *strsec;
1150 ElfW(RelM) *rel, *relend;
1151 ElfW(Sym) *symtab, *extsym;
1152 const char *strtab, *name;
1153 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001154
Eric Andersen21adca72000-12-06 18:18:26 +00001155 for (i = 0; i < f->header.e_shnum; ++i) {
1156 relsec = f->sections[i];
1157 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001158 continue;
1159
Eric Andersen21adca72000-12-06 18:18:26 +00001160 symsec = f->sections[relsec->header.sh_link];
1161 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001162
Eric Andersen21adca72000-12-06 18:18:26 +00001163 rel = (ElfW(RelM) *) relsec->contents;
1164 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1165 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001166 strtab = (const char *) strsec->contents;
1167
1168 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001169 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001170
1171 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001172#if defined(__arm__)
1173 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001174 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001175#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001176 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001177 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001178#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001179 case R_386_GOT32:
1180 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001181#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001182 case R_68K_GOT32:
1183 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001184#endif
1185
1186#if defined(__powerpc__)
1187 case R_PPC_REL24:
1188 pltneeded = 1;
1189 break;
1190#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001191
1192#if defined(__arm__)
1193 case R_ARM_PC24:
1194 case R_ARM_PLT32:
1195 pltneeded = 1;
1196 break;
1197
1198 case R_ARM_GOTPC:
1199 case R_ARM_GOTOFF:
1200 gotneeded = 1;
1201 if (got_offset == 0)
1202 got_offset = 4;
1203#elif defined(__sh__)
1204 case R_SH_GOTPC:
1205 case R_SH_GOTOFF:
1206 gotneeded = 1;
1207#elif defined(__i386__)
1208 case R_386_GOTPC:
1209 case R_386_GOTOFF:
1210 gotneeded = 1;
1211#endif
1212
1213 default:
1214 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001215 }
1216
Eric Andersen21adca72000-12-06 18:18:26 +00001217 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001218 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001219 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001220 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001221 }
1222 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001223#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001224 if (!intsym->gotent.offset_done) {
1225 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001226 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001227 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001228 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001229#endif
1230#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001231 if (pltneeded && intsym->pltent.allocated == 0) {
1232 intsym->pltent.allocated = 1;
1233 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001234 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001235 intsym->pltent.inited = 0;
1236 pltneeded = 0;
1237 }
1238#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001239 }
1240 }
Eric Andersen21adca72000-12-06 18:18:26 +00001241
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001242#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001243 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001244 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001245
Eric Andersene76c3b02001-04-05 03:14:39 +00001246 if (myrelsec) {
1247 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001248 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001249 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001250 BB_GOT_ENTRY_SIZE,
1251 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001252 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001253 }
1254
Eric Andersene76c3b02001-04-05 03:14:39 +00001255 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001256 }
Eric Andersen21adca72000-12-06 18:18:26 +00001257#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001258
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001259#if defined(BB_USE_PLT_ENTRIES)
1260 if (plt_offset)
1261 ifile->plt = obj_create_alloced_section(f, ".plt",
1262 BB_PLT_ENTRY_SIZE,
1263 plt_offset);
1264#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001265#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001266 return 1;
1267}
1268
Eric Andersen044228d2001-07-17 01:12:36 +00001269static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001270{
1271 return 1;
1272}
1273
1274
1275/*======================================================================*/
1276
1277/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001278static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001279{
1280 unsigned long h = 0;
1281 unsigned long g;
1282 unsigned char ch;
1283
1284 while (n > 0) {
1285 ch = *name++;
1286 h = (h << 4) + ch;
1287 if ((g = (h & 0xf0000000)) != 0) {
1288 h ^= g >> 24;
1289 h &= ~g;
1290 }
1291 n--;
1292 }
1293 return h;
1294}
1295
Eric Andersen044228d2001-07-17 01:12:36 +00001296static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001297{
1298 return obj_elf_hash_n(name, strlen(name));
1299}
1300
1301#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1302/* Get the kernel version in the canonical integer form. */
1303
1304static int get_kernel_version(char str[STRVERSIONLEN])
1305{
1306 struct utsname uts_info;
Eric Andersen044228d2001-07-17 01:12:36 +00001307 int kv;
Eric Andersen9f16d612000-06-12 23:11:16 +00001308
1309 if (uname(&uts_info) < 0)
1310 return -1;
1311 strncpy(str, uts_info.release, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00001312
Eric Andersen044228d2001-07-17 01:12:36 +00001313 kv = get_kernel_revision();
1314 if(kv==0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001315 return -1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001316}
1317
1318/* String comparison for non-co-versioned kernel and module. */
1319
1320static int ncv_strcmp(const char *a, const char *b)
1321{
1322 size_t alen = strlen(a), blen = strlen(b);
1323
1324 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1325 return strncmp(a, b, alen);
1326 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1327 return strncmp(a, b, blen);
1328 else
1329 return strcmp(a, b);
1330}
1331
1332/* String hashing for non-co-versioned kernel and module. Here
1333 we are simply forced to drop the crc from the hash. */
1334
1335static unsigned long ncv_symbol_hash(const char *str)
1336{
1337 size_t len = strlen(str);
1338 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1339 len -= 10;
1340 return obj_elf_hash_n(str, len);
1341}
1342
Eric Andersen044228d2001-07-17 01:12:36 +00001343static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001344obj_set_symbol_compare(struct obj_file *f,
1345 int (*cmp) (const char *, const char *),
1346 unsigned long (*hash) (const char *))
1347{
1348 if (cmp)
1349 f->symbol_cmp = cmp;
1350 if (hash) {
1351 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1352 int i;
1353
1354 f->symbol_hash = hash;
1355
1356 memcpy(tmptab, f->symtab, sizeof(tmptab));
1357 memset(f->symtab, 0, sizeof(f->symtab));
1358
1359 for (i = 0; i < HASH_BUCKETS; ++i)
1360 for (sym = tmptab[i]; sym; sym = next) {
1361 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1362 next = sym->next;
1363 sym->next = f->symtab[h];
1364 f->symtab[h] = sym;
1365 }
1366 }
1367}
1368
1369#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1370
Eric Andersen044228d2001-07-17 01:12:36 +00001371static struct obj_symbol *
1372obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001373 unsigned long symidx, int info,
1374 int secidx, ElfW(Addr) value,
1375 unsigned long size)
1376{
1377 struct obj_symbol *sym;
1378 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1379 int n_type = ELFW(ST_TYPE) (info);
1380 int n_binding = ELFW(ST_BIND) (info);
1381
1382 for (sym = f->symtab[hash]; sym; sym = sym->next)
1383 if (f->symbol_cmp(sym->name, name) == 0) {
1384 int o_secidx = sym->secidx;
1385 int o_info = sym->info;
1386 int o_type = ELFW(ST_TYPE) (o_info);
1387 int o_binding = ELFW(ST_BIND) (o_info);
1388
1389 /* A redefinition! Is it legal? */
1390
1391 if (secidx == SHN_UNDEF)
1392 return sym;
1393 else if (o_secidx == SHN_UNDEF)
1394 goto found;
1395 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1396 /* Cope with local and global symbols of the same name
1397 in the same object file, as might have been created
1398 by ld -r. The only reason locals are now seen at this
1399 level at all is so that we can do semi-sensible things
1400 with parameters. */
1401
1402 struct obj_symbol *nsym, **p;
1403
1404 nsym = arch_new_symbol();
1405 nsym->next = sym->next;
1406 nsym->ksymidx = -1;
1407
1408 /* Excise the old (local) symbol from the hash chain. */
1409 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1410 continue;
1411 *p = sym = nsym;
1412 goto found;
1413 } else if (n_binding == STB_LOCAL) {
1414 /* Another symbol of the same name has already been defined.
1415 Just add this to the local table. */
1416 sym = arch_new_symbol();
1417 sym->next = NULL;
1418 sym->ksymidx = -1;
1419 f->local_symtab[symidx] = sym;
1420 goto found;
1421 } else if (n_binding == STB_WEAK)
1422 return sym;
1423 else if (o_binding == STB_WEAK)
1424 goto found;
1425 /* Don't unify COMMON symbols with object types the programmer
1426 doesn't expect. */
1427 else if (secidx == SHN_COMMON
1428 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1429 return sym;
1430 else if (o_secidx == SHN_COMMON
1431 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1432 goto found;
1433 else {
1434 /* Don't report an error if the symbol is coming from
1435 the kernel or some external module. */
1436 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001437 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001438 return sym;
1439 }
1440 }
1441
1442 /* Completely new symbol. */
1443 sym = arch_new_symbol();
1444 sym->next = f->symtab[hash];
1445 f->symtab[hash] = sym;
1446 sym->ksymidx = -1;
1447
Eric Andersen66ca9482001-06-28 21:36:06 +00001448 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1449 if (symidx >= f->local_symtab_size)
1450 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1451 name, (long) symidx, (long) f->local_symtab_size);
1452 else
1453 f->local_symtab[symidx] = sym;
1454 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001455
1456 found:
1457 sym->name = name;
1458 sym->value = value;
1459 sym->size = size;
1460 sym->secidx = secidx;
1461 sym->info = info;
1462
1463 return sym;
1464}
1465
Eric Andersen044228d2001-07-17 01:12:36 +00001466static struct obj_symbol *
1467obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001468{
1469 struct obj_symbol *sym;
1470 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1471
1472 for (sym = f->symtab[hash]; sym; sym = sym->next)
1473 if (f->symbol_cmp(sym->name, name) == 0)
1474 return sym;
1475
1476 return NULL;
1477}
1478
Eric Andersen044228d2001-07-17 01:12:36 +00001479static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001480 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1481{
1482 if (sym) {
1483 if (sym->secidx >= SHN_LORESERVE)
1484 return sym->value;
1485
1486 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1487 } else {
1488 /* As a special case, a NULL sym has value zero. */
1489 return 0;
1490 }
1491}
1492
Eric Andersen044228d2001-07-17 01:12:36 +00001493static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001494{
1495 int i, n = f->header.e_shnum;
1496
1497 for (i = 0; i < n; ++i)
1498 if (strcmp(f->sections[i]->name, name) == 0)
1499 return f->sections[i];
1500
1501 return NULL;
1502}
1503
1504static int obj_load_order_prio(struct obj_section *a)
1505{
1506 unsigned long af, ac;
1507
1508 af = a->header.sh_flags;
1509
1510 ac = 0;
1511 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1512 strcmp(a->name + 5, ".init"))
1513 ac |= 32;
1514 if (af & SHF_ALLOC)
1515 ac |= 16;
1516 if (!(af & SHF_WRITE))
1517 ac |= 8;
1518 if (af & SHF_EXECINSTR)
1519 ac |= 4;
1520 if (a->header.sh_type != SHT_NOBITS)
1521 ac |= 2;
1522
1523 return ac;
1524}
1525
Eric Andersen044228d2001-07-17 01:12:36 +00001526static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001527obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1528{
1529 struct obj_section **p;
1530 int prio = obj_load_order_prio(sec);
1531 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1532 if (obj_load_order_prio(*p) < prio)
1533 break;
1534 sec->load_next = *p;
1535 *p = sec;
1536}
1537
Eric Andersen044228d2001-07-17 01:12:36 +00001538static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001539 const char *name,
1540 unsigned long align,
1541 unsigned long size)
1542{
1543 int newidx = f->header.e_shnum++;
1544 struct obj_section *sec;
1545
1546 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1547 f->sections[newidx] = sec = arch_new_section();
1548
1549 memset(sec, 0, sizeof(*sec));
1550 sec->header.sh_type = SHT_PROGBITS;
1551 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1552 sec->header.sh_size = size;
1553 sec->header.sh_addralign = align;
1554 sec->name = name;
1555 sec->idx = newidx;
1556 if (size)
1557 sec->contents = xmalloc(size);
1558
1559 obj_insert_section_load_order(f, sec);
1560
1561 return sec;
1562}
1563
Eric Andersen044228d2001-07-17 01:12:36 +00001564static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001565 const char *name,
1566 unsigned long align,
1567 unsigned long size)
1568{
1569 int newidx = f->header.e_shnum++;
1570 struct obj_section *sec;
1571
1572 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1573 f->sections[newidx] = sec = arch_new_section();
1574
1575 memset(sec, 0, sizeof(*sec));
1576 sec->header.sh_type = SHT_PROGBITS;
1577 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1578 sec->header.sh_size = size;
1579 sec->header.sh_addralign = align;
1580 sec->name = name;
1581 sec->idx = newidx;
1582 if (size)
1583 sec->contents = xmalloc(size);
1584
1585 sec->load_next = f->load_order;
1586 f->load_order = sec;
1587 if (f->load_order_search_start == &f->load_order)
1588 f->load_order_search_start = &sec->load_next;
1589
1590 return sec;
1591}
1592
Eric Andersen044228d2001-07-17 01:12:36 +00001593static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001594{
1595 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001596 if (more) {
1597 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1598 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001599 return sec->contents + oldsize;
1600}
1601
1602
Eric Andersen9f16d612000-06-12 23:11:16 +00001603/* Conditionally add the symbols from the given symbol set to the
1604 new module. */
1605
1606static int
1607add_symbols_from(
1608 struct obj_file *f,
1609 int idx, struct new_module_symbol *syms, size_t nsyms)
1610{
1611 struct new_module_symbol *s;
1612 size_t i;
1613 int used = 0;
1614
1615 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1616
1617 /* Only add symbols that are already marked external. If we
1618 override locals we may cause problems for argument initialization.
1619 We will also create a false dependency on the module. */
1620 struct obj_symbol *sym;
1621
1622 sym = obj_find_symbol(f, (char *) s->name);
1623 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1624 sym = obj_add_symbol(f, (char *) s->name, -1,
1625 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1626 idx, s->value, 0);
1627 /* Did our symbol just get installed? If so, mark the
1628 module as "used". */
1629 if (sym->secidx == idx)
1630 used = 1;
1631 }
1632 }
1633
1634 return used;
1635}
1636
1637static void add_kernel_symbols(struct obj_file *f)
1638{
1639 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001640 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001641
1642 /* Add module symbols first. */
1643
1644 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1645 if (m->nsyms
1646 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1647 m->nsyms)) m->used = 1, ++nused;
1648
1649 n_ext_modules_used = nused;
1650
1651 /* And finally the symbols from the kernel proper. */
1652
1653 if (nksyms)
1654 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1655}
1656
1657static char *get_modinfo_value(struct obj_file *f, const char *key)
1658{
1659 struct obj_section *sec;
1660 char *p, *v, *n, *ep;
1661 size_t klen = strlen(key);
1662
1663 sec = obj_find_section(f, ".modinfo");
1664 if (sec == NULL)
1665 return NULL;
1666 p = sec->contents;
1667 ep = p + sec->header.sh_size;
1668 while (p < ep) {
1669 v = strchr(p, '=');
1670 n = strchr(p, '\0');
1671 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001672 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001673 return v + 1;
1674 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001675 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001676 return n;
1677 }
1678 p = n + 1;
1679 }
1680
1681 return NULL;
1682}
1683
1684
1685/*======================================================================*/
1686/* Functions relating to module loading in pre 2.1 kernels. */
1687
1688static int
1689old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1690{
1691 while (argc > 0) {
1692 char *p, *q;
1693 struct obj_symbol *sym;
1694 int *loc;
1695
1696 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001697 if ((q = strchr(p, '=')) == NULL) {
1698 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001699 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001700 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001701 *q++ = '\0';
1702
1703 sym = obj_find_symbol(f, p);
1704
1705 /* Also check that the parameter was not resolved from the kernel. */
1706 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001707 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001708 return 0;
1709 }
1710
1711 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1712
1713 /* Do C quoting if we begin with a ". */
1714 if (*q == '"') {
1715 char *r, *str;
1716
1717 str = alloca(strlen(q));
1718 for (r = str, q++; *q != '"'; ++q, ++r) {
1719 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001720 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001721 return 0;
1722 } else if (*q == '\\')
1723 switch (*++q) {
1724 case 'a':
1725 *r = '\a';
1726 break;
1727 case 'b':
1728 *r = '\b';
1729 break;
1730 case 'e':
1731 *r = '\033';
1732 break;
1733 case 'f':
1734 *r = '\f';
1735 break;
1736 case 'n':
1737 *r = '\n';
1738 break;
1739 case 'r':
1740 *r = '\r';
1741 break;
1742 case 't':
1743 *r = '\t';
1744 break;
1745
1746 case '0':
1747 case '1':
1748 case '2':
1749 case '3':
1750 case '4':
1751 case '5':
1752 case '6':
1753 case '7':
1754 {
1755 int c = *q - '0';
1756 if (q[1] >= '0' && q[1] <= '7') {
1757 c = (c * 8) + *++q - '0';
1758 if (q[1] >= '0' && q[1] <= '7')
1759 c = (c * 8) + *++q - '0';
1760 }
1761 *r = c;
1762 }
1763 break;
1764
1765 default:
1766 *r = *q;
1767 break;
1768 } else
1769 *r = *q;
1770 }
1771 *r = '\0';
1772 obj_string_patch(f, sym->secidx, sym->value, str);
1773 } else if (*q >= '0' && *q <= '9') {
1774 do
1775 *loc++ = strtoul(q, &q, 0);
1776 while (*q++ == ',');
1777 } else {
1778 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001779 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001780 char *r; /* To search for commas */
1781
1782 /* Break the string with comas */
1783 while ((r = strchr(q, ',')) != (char *) NULL) {
1784 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001785 obj_string_patch(f, sym->secidx, myloc - contents, q);
1786 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001787 q = r;
1788 }
1789
1790 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001791 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001792 }
1793
1794 argc--, argv++;
1795 }
1796
1797 return 1;
1798}
1799
1800#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1801static int old_is_module_checksummed(struct obj_file *f)
1802{
1803 return obj_find_symbol(f, "Using_Versions") != NULL;
1804}
1805/* Get the module's kernel version in the canonical integer form. */
1806
1807static int
1808old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1809{
1810 struct obj_symbol *sym;
1811 char *p, *q;
1812 int a, b, c;
1813
1814 sym = obj_find_symbol(f, "kernel_version");
1815 if (sym == NULL)
1816 return -1;
1817
1818 p = f->sections[sym->secidx]->contents + sym->value;
1819 strncpy(str, p, STRVERSIONLEN);
1820
1821 a = strtoul(p, &p, 10);
1822 if (*p != '.')
1823 return -1;
1824 b = strtoul(p + 1, &p, 10);
1825 if (*p != '.')
1826 return -1;
1827 c = strtoul(p + 1, &q, 10);
1828 if (p + 1 == q)
1829 return -1;
1830
1831 return a << 16 | b << 8 | c;
1832}
1833
1834#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1835
Eric Andersenf5d5e772001-01-24 23:34:48 +00001836#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001837
1838/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1839
Eric Andersen8c185f92000-09-22 00:38:07 +00001840static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001841{
1842 struct old_kernel_sym *ks, *k;
1843 struct new_module_symbol *s;
1844 struct external_module *mod;
1845 int nks, nms, nmod, i;
1846
1847 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001848 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001849 if (nks)
1850 perror_msg("get_kernel_syms: %s", m_name);
1851 else
1852 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001853 return 0;
1854 }
1855
1856 ks = k = xmalloc(nks * sizeof(*ks));
1857
1858 if (get_kernel_syms(ks) != nks) {
1859 perror("inconsistency with get_kernel_syms -- is someone else "
1860 "playing with modules?");
1861 free(ks);
1862 return 0;
1863 }
1864
1865 /* Collect the module information. */
1866
1867 mod = NULL;
1868 nmod = -1;
1869
1870 while (k->name[0] == '#' && k->name[1]) {
1871 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001872
1873 /* Find out how many symbols this module has. */
1874 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1875 continue;
1876 nms = k2 - k - 1;
1877
1878 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1879 mod[nmod].name = k->name + 1;
1880 mod[nmod].addr = k->value;
1881 mod[nmod].used = 0;
1882 mod[nmod].nsyms = nms;
1883 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1884
1885 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1886 s->name = (unsigned long) k->name;
1887 s->value = k->value;
1888 }
1889
1890 k = k2;
1891 }
1892
1893 ext_modules = mod;
1894 n_ext_modules = nmod + 1;
1895
1896 /* Now collect the symbols for the kernel proper. */
1897
1898 if (k->name[0] == '#')
1899 ++k;
1900
1901 nksyms = nms = nks - (k - ks);
1902 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1903
1904 for (i = 0; i < nms; ++i, ++s, ++k) {
1905 s->name = (unsigned long) k->name;
1906 s->value = k->value;
1907 }
1908
1909 return 1;
1910}
1911
1912/* Return the kernel symbol checksum version, or zero if not used. */
1913
1914static int old_is_kernel_checksummed(void)
1915{
1916 /* Using_Versions is the first symbol. */
1917 if (nksyms > 0
1918 && strcmp((char *) ksyms[0].name,
1919 "Using_Versions") == 0) return ksyms[0].value;
1920 else
1921 return 0;
1922}
1923
1924
1925static int old_create_mod_use_count(struct obj_file *f)
1926{
1927 struct obj_section *sec;
1928
1929 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1930 sizeof(long));
1931
1932 obj_add_symbol(f, "mod_use_count_", -1,
1933 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1934 sizeof(long));
1935
1936 return 1;
1937}
1938
1939static int
1940old_init_module(const char *m_name, struct obj_file *f,
1941 unsigned long m_size)
1942{
1943 char *image;
1944 struct old_mod_routines routines;
1945 struct old_symbol_table *symtab;
1946 int ret;
1947
1948 /* Create the symbol table */
1949 {
1950 int nsyms = 0, strsize = 0, total;
1951
1952 /* Size things first... */
1953 if (flag_export) {
1954 int i;
1955 for (i = 0; i < HASH_BUCKETS; ++i) {
1956 struct obj_symbol *sym;
1957 for (sym = f->symtab[i]; sym; sym = sym->next)
1958 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1959 && sym->secidx <= SHN_HIRESERVE)
1960 {
1961 sym->ksymidx = nsyms++;
1962 strsize += strlen(sym->name) + 1;
1963 }
1964 }
1965 }
1966
1967 total = (sizeof(struct old_symbol_table)
1968 + nsyms * sizeof(struct old_module_symbol)
1969 + n_ext_modules_used * sizeof(struct old_module_ref)
1970 + strsize);
1971 symtab = xmalloc(total);
1972 symtab->size = total;
1973 symtab->n_symbols = nsyms;
1974 symtab->n_refs = n_ext_modules_used;
1975
1976 if (flag_export && nsyms) {
1977 struct old_module_symbol *ksym;
1978 char *str;
1979 int i;
1980
1981 ksym = symtab->symbol;
1982 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1983 + n_ext_modules_used * sizeof(struct old_module_ref));
1984
1985 for (i = 0; i < HASH_BUCKETS; ++i) {
1986 struct obj_symbol *sym;
1987 for (sym = f->symtab[i]; sym; sym = sym->next)
1988 if (sym->ksymidx >= 0) {
1989 ksym->addr = obj_symbol_final_value(f, sym);
1990 ksym->name =
1991 (unsigned long) str - (unsigned long) symtab;
1992
Matt Kraai70a78552001-01-04 02:00:17 +00001993 strcpy(str, sym->name);
1994 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001995 ksym++;
1996 }
1997 }
1998 }
1999
2000 if (n_ext_modules_used) {
2001 struct old_module_ref *ref;
2002 int i;
2003
2004 ref = (struct old_module_ref *)
2005 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2006
2007 for (i = 0; i < n_ext_modules; ++i)
2008 if (ext_modules[i].used)
2009 ref++->module = ext_modules[i].addr;
2010 }
2011 }
2012
2013 /* Fill in routines. */
2014
2015 routines.init =
2016 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2017 routines.cleanup =
2018 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2019
2020 /* Whew! All of the initialization is complete. Collect the final
2021 module image and give it to the kernel. */
2022
2023 image = xmalloc(m_size);
2024 obj_create_image(f, image);
2025
2026 /* image holds the complete relocated module, accounting correctly for
2027 mod_use_count. However the old module kernel support assume that
2028 it is receiving something which does not contain mod_use_count. */
2029 ret = old_sys_init_module(m_name, image + sizeof(long),
2030 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2031 : 0), &routines, symtab);
2032 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002033 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002034
2035 free(image);
2036 free(symtab);
2037
2038 return ret == 0;
2039}
2040
2041#else
2042
2043#define old_create_mod_use_count(x) TRUE
2044#define old_init_module(x, y, z) TRUE
2045
Eric Andersenf5d5e772001-01-24 23:34:48 +00002046#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002047
2048
2049
2050/*======================================================================*/
2051/* Functions relating to module loading after 2.1.18. */
2052
2053static int
2054new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2055{
2056 while (argc > 0) {
2057 char *p, *q, *key;
2058 struct obj_symbol *sym;
2059 char *contents, *loc;
2060 int min, max, n;
2061
2062 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002063 if ((q = strchr(p, '=')) == NULL) {
2064 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002065 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002066 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002067
2068 key = alloca(q - p + 6);
2069 memcpy(key, "parm_", 5);
2070 memcpy(key + 5, p, q - p);
2071 key[q - p + 5] = 0;
2072
2073 p = get_modinfo_value(f, key);
2074 key += 5;
2075 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002076 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002077 return 0;
2078 }
2079
2080 sym = obj_find_symbol(f, key);
2081
2082 /* Also check that the parameter was not resolved from the kernel. */
2083 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002084 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002085 return 0;
2086 }
2087
2088 if (isdigit(*p)) {
2089 min = strtoul(p, &p, 10);
2090 if (*p == '-')
2091 max = strtoul(p + 1, &p, 10);
2092 else
2093 max = min;
2094 } else
2095 min = max = 1;
2096
2097 contents = f->sections[sym->secidx]->contents;
2098 loc = contents + sym->value;
2099 n = (*++q != '\0');
2100
2101 while (1) {
2102 if ((*p == 's') || (*p == 'c')) {
2103 char *str;
2104
2105 /* Do C quoting if we begin with a ", else slurp the lot. */
2106 if (*q == '"') {
2107 char *r;
2108
2109 str = alloca(strlen(q));
2110 for (r = str, q++; *q != '"'; ++q, ++r) {
2111 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002112 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002113 key);
2114 return 0;
2115 } else if (*q == '\\')
2116 switch (*++q) {
2117 case 'a':
2118 *r = '\a';
2119 break;
2120 case 'b':
2121 *r = '\b';
2122 break;
2123 case 'e':
2124 *r = '\033';
2125 break;
2126 case 'f':
2127 *r = '\f';
2128 break;
2129 case 'n':
2130 *r = '\n';
2131 break;
2132 case 'r':
2133 *r = '\r';
2134 break;
2135 case 't':
2136 *r = '\t';
2137 break;
2138
2139 case '0':
2140 case '1':
2141 case '2':
2142 case '3':
2143 case '4':
2144 case '5':
2145 case '6':
2146 case '7':
2147 {
2148 int c = *q - '0';
2149 if (q[1] >= '0' && q[1] <= '7') {
2150 c = (c * 8) + *++q - '0';
2151 if (q[1] >= '0' && q[1] <= '7')
2152 c = (c * 8) + *++q - '0';
2153 }
2154 *r = c;
2155 }
2156 break;
2157
2158 default:
2159 *r = *q;
2160 break;
2161 } else
2162 *r = *q;
2163 }
2164 *r = '\0';
2165 ++q;
2166 } else {
2167 char *r;
2168
2169 /* In this case, the string is not quoted. We will break
2170 it using the coma (like for ints). If the user wants to
2171 include comas in a string, he just has to quote it */
2172
2173 /* Search the next coma */
2174 r = strchr(q, ',');
2175
2176 /* Found ? */
2177 if (r != (char *) NULL) {
2178 /* Recopy the current field */
2179 str = alloca(r - q + 1);
2180 memcpy(str, q, r - q);
2181
2182 /* I don't know if it is usefull, as the previous case
2183 doesn't null terminate the string ??? */
2184 str[r - q] = '\0';
2185
2186 /* Keep next fields */
2187 q = r;
2188 } else {
2189 /* last string */
2190 str = q;
2191 q = "";
2192 }
2193 }
2194
2195 if (*p == 's') {
2196 /* Normal string */
2197 obj_string_patch(f, sym->secidx, loc - contents, str);
2198 loc += tgt_sizeof_char_p;
2199 } else {
2200 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002201 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002202
2203 /* Get the size of each member */
2204 /* Probably we should do that outside the loop ? */
2205 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002206 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002207 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002208 return 0;
2209 }
2210 charssize = strtoul(p + 1, (char **) NULL, 10);
2211
2212 /* Check length */
2213 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002214 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002215 charssize - 1);
2216 return 0;
2217 }
2218
2219 /* Copy to location */
2220 strcpy((char *) loc, str);
2221 loc += charssize;
2222 }
2223 } else {
2224 long v = strtoul(q, &q, 0);
2225 switch (*p) {
2226 case 'b':
2227 *loc++ = v;
2228 break;
2229 case 'h':
2230 *(short *) loc = v;
2231 loc += tgt_sizeof_short;
2232 break;
2233 case 'i':
2234 *(int *) loc = v;
2235 loc += tgt_sizeof_int;
2236 break;
2237 case 'l':
2238 *(long *) loc = v;
2239 loc += tgt_sizeof_long;
2240 break;
2241
2242 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002243 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002244 return 0;
2245 }
2246 }
2247
2248 retry_end_of_value:
2249 switch (*q) {
2250 case '\0':
2251 goto end_of_arg;
2252
2253 case ' ':
2254 case '\t':
2255 case '\n':
2256 case '\r':
2257 ++q;
2258 goto retry_end_of_value;
2259
2260 case ',':
2261 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002262 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002263 return 0;
2264 }
2265 ++q;
2266 break;
2267
2268 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002269 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002270 return 0;
2271 }
2272 }
2273
2274 end_of_arg:
2275 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002276 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002277 return 0;
2278 }
2279
2280 argc--, argv++;
2281 }
2282
2283 return 1;
2284}
2285
2286#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2287static int new_is_module_checksummed(struct obj_file *f)
2288{
2289 const char *p = get_modinfo_value(f, "using_checksums");
2290 if (p)
2291 return atoi(p);
2292 else
2293 return 0;
2294}
2295
2296/* Get the module's kernel version in the canonical integer form. */
2297
2298static int
2299new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2300{
2301 char *p, *q;
2302 int a, b, c;
2303
2304 p = get_modinfo_value(f, "kernel_version");
2305 if (p == NULL)
2306 return -1;
2307 strncpy(str, p, STRVERSIONLEN);
2308
2309 a = strtoul(p, &p, 10);
2310 if (*p != '.')
2311 return -1;
2312 b = strtoul(p + 1, &p, 10);
2313 if (*p != '.')
2314 return -1;
2315 c = strtoul(p + 1, &q, 10);
2316 if (p + 1 == q)
2317 return -1;
2318
2319 return a << 16 | b << 8 | c;
2320}
2321
2322#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2323
2324
Eric Andersenf5d5e772001-01-24 23:34:48 +00002325#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002326
2327/* Fetch the loaded modules, and all currently exported symbols. */
2328
2329static int new_get_kernel_symbols(void)
2330{
2331 char *module_names, *mn;
2332 struct external_module *modules, *m;
2333 struct new_module_symbol *syms, *s;
2334 size_t ret, bufsize, nmod, nsyms, i, j;
2335
2336 /* Collect the loaded modules. */
2337
2338 module_names = xmalloc(bufsize = 256);
2339 retry_modules_load:
2340 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002341 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002342 module_names = xrealloc(module_names, bufsize = ret);
2343 goto retry_modules_load;
2344 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002345 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002346 return 0;
2347 }
2348
2349 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002350
2351 /* Collect the modules' symbols. */
2352
Mark Whitley94fd4802001-03-12 23:08:34 +00002353 if (nmod){
2354 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2355 memset(modules, 0, nmod * sizeof(*modules));
2356 for (i = 0, mn = module_names, m = modules;
2357 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2358 struct new_module_info info;
2359
2360 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2361 if (errno == ENOENT) {
2362 /* The module was removed out from underneath us. */
2363 continue;
2364 }
2365 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002366 return 0;
2367 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002368
2369 syms = xmalloc(bufsize = 1024);
2370 retry_mod_sym_load:
2371 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2372 switch (errno) {
2373 case ENOSPC:
2374 syms = xrealloc(syms, bufsize = ret);
2375 goto retry_mod_sym_load;
2376 case ENOENT:
2377 /* The module was removed out from underneath us. */
2378 continue;
2379 default:
2380 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2381 return 0;
2382 }
2383 }
2384 nsyms = ret;
2385
2386 m->name = mn;
2387 m->addr = info.addr;
2388 m->nsyms = nsyms;
2389 m->syms = syms;
2390
2391 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2392 s->name += (unsigned long) syms;
2393 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002394 }
2395 }
2396
2397 /* Collect the kernel's symbols. */
2398
2399 syms = xmalloc(bufsize = 16 * 1024);
2400 retry_kern_sym_load:
2401 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002402 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002403 syms = xrealloc(syms, bufsize = ret);
2404 goto retry_kern_sym_load;
2405 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002406 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002407 return 0;
2408 }
2409 nksyms = nsyms = ret;
2410 ksyms = syms;
2411
2412 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2413 s->name += (unsigned long) syms;
2414 }
2415 return 1;
2416}
2417
2418
2419/* Return the kernel symbol checksum version, or zero if not used. */
2420
2421static int new_is_kernel_checksummed(void)
2422{
2423 struct new_module_symbol *s;
2424 size_t i;
2425
2426 /* Using_Versions is not the first symbol, but it should be in there. */
2427
2428 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2429 if (strcmp((char *) s->name, "Using_Versions") == 0)
2430 return s->value;
2431
2432 return 0;
2433}
2434
2435
2436static int new_create_this_module(struct obj_file *f, const char *m_name)
2437{
2438 struct obj_section *sec;
2439
2440 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2441 sizeof(struct new_module));
2442 memset(sec->contents, 0, sizeof(struct new_module));
2443
2444 obj_add_symbol(f, "__this_module", -1,
2445 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2446 sizeof(struct new_module));
2447
2448 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2449 m_name);
2450
2451 return 1;
2452}
2453
2454
2455static int new_create_module_ksymtab(struct obj_file *f)
2456{
2457 struct obj_section *sec;
2458 int i;
2459
2460 /* We must always add the module references. */
2461
2462 if (n_ext_modules_used) {
2463 struct new_module_ref *dep;
2464 struct obj_symbol *tm;
2465
2466 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2467 (sizeof(struct new_module_ref)
2468 * n_ext_modules_used));
2469 if (!sec)
2470 return 0;
2471
2472 tm = obj_find_symbol(f, "__this_module");
2473 dep = (struct new_module_ref *) sec->contents;
2474 for (i = 0; i < n_ext_modules; ++i)
2475 if (ext_modules[i].used) {
2476 dep->dep = ext_modules[i].addr;
2477 obj_symbol_patch(f, sec->idx,
2478 (char *) &dep->ref - sec->contents, tm);
2479 dep->next_ref = 0;
2480 ++dep;
2481 }
2482 }
2483
2484 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2485 size_t nsyms;
2486 int *loaded;
2487
2488 sec =
2489 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2490 0);
2491
2492 /* We don't want to export symbols residing in sections that
2493 aren't loaded. There are a number of these created so that
2494 we make sure certain module options don't appear twice. */
2495
2496 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2497 while (--i >= 0)
2498 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2499
2500 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2501 struct obj_symbol *sym;
2502 for (sym = f->symtab[i]; sym; sym = sym->next)
2503 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2504 && sym->secidx <= SHN_HIRESERVE
2505 && (sym->secidx >= SHN_LORESERVE
2506 || loaded[sym->secidx])) {
2507 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2508
2509 obj_symbol_patch(f, sec->idx, ofs, sym);
2510 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2511 sym->name);
2512
2513 nsyms++;
2514 }
2515 }
2516
2517 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2518 }
2519
2520 return 1;
2521}
2522
2523
2524static int
2525new_init_module(const char *m_name, struct obj_file *f,
2526 unsigned long m_size)
2527{
2528 struct new_module *module;
2529 struct obj_section *sec;
2530 void *image;
2531 int ret;
2532 tgt_long m_addr;
2533
2534 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002535 if (!sec || !sec->contents) {
2536 perror_msg_and_die("corrupt module %s?",m_name);
2537 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002538 module = (struct new_module *) sec->contents;
2539 m_addr = sec->header.sh_addr;
2540
2541 module->size_of_struct = sizeof(*module);
2542 module->size = m_size;
2543 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2544
2545 sec = obj_find_section(f, "__ksymtab");
2546 if (sec && sec->header.sh_size) {
2547 module->syms = sec->header.sh_addr;
2548 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2549 }
2550
2551 if (n_ext_modules_used) {
2552 sec = obj_find_section(f, ".kmodtab");
2553 module->deps = sec->header.sh_addr;
2554 module->ndeps = n_ext_modules_used;
2555 }
2556
2557 module->init =
2558 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2559 module->cleanup =
2560 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2561
2562 sec = obj_find_section(f, "__ex_table");
2563 if (sec) {
2564 module->ex_table_start = sec->header.sh_addr;
2565 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2566 }
2567
2568 sec = obj_find_section(f, ".text.init");
2569 if (sec) {
2570 module->runsize = sec->header.sh_addr - m_addr;
2571 }
2572 sec = obj_find_section(f, ".data.init");
2573 if (sec) {
2574 if (!module->runsize ||
2575 module->runsize > sec->header.sh_addr - m_addr)
2576 module->runsize = sec->header.sh_addr - m_addr;
2577 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002578 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2579 if (sec && sec->header.sh_size) {
2580 module->archdata_start = (void*)sec->header.sh_addr;
2581 module->archdata_end = module->archdata_start + sec->header.sh_size;
2582 }
2583 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2584 if (sec && sec->header.sh_size) {
2585 module->kallsyms_start = (void*)sec->header.sh_addr;
2586 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2587 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002588
2589 if (!arch_init_module(f, module))
2590 return 0;
2591
2592 /* Whew! All of the initialization is complete. Collect the final
2593 module image and give it to the kernel. */
2594
2595 image = xmalloc(m_size);
2596 obj_create_image(f, image);
2597
Eric Andersen64c8b172001-04-05 07:33:10 +00002598 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002599 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002600 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002601
2602 free(image);
2603
2604 return ret == 0;
2605}
2606
2607#else
2608
2609#define new_init_module(x, y, z) TRUE
2610#define new_create_this_module(x, y) 0
2611#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002612#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002613
Eric Andersenf5d5e772001-01-24 23:34:48 +00002614#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002615
2616
2617/*======================================================================*/
2618
Eric Andersen044228d2001-07-17 01:12:36 +00002619static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002620obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2621 const char *string)
2622{
2623 struct obj_string_patch *p;
2624 struct obj_section *strsec;
2625 size_t len = strlen(string) + 1;
2626 char *loc;
2627
2628 p = xmalloc(sizeof(*p));
2629 p->next = f->string_patches;
2630 p->reloc_secidx = secidx;
2631 p->reloc_offset = offset;
2632 f->string_patches = p;
2633
2634 strsec = obj_find_section(f, ".kstrtab");
2635 if (strsec == NULL) {
2636 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2637 p->string_offset = 0;
2638 loc = strsec->contents;
2639 } else {
2640 p->string_offset = strsec->header.sh_size;
2641 loc = obj_extend_section(strsec, len);
2642 }
2643 memcpy(loc, string, len);
2644
2645 return 1;
2646}
2647
Eric Andersen044228d2001-07-17 01:12:36 +00002648static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002649obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2650 struct obj_symbol *sym)
2651{
2652 struct obj_symbol_patch *p;
2653
2654 p = xmalloc(sizeof(*p));
2655 p->next = f->symbol_patches;
2656 p->reloc_secidx = secidx;
2657 p->reloc_offset = offset;
2658 p->sym = sym;
2659 f->symbol_patches = p;
2660
2661 return 1;
2662}
2663
Eric Andersen044228d2001-07-17 01:12:36 +00002664static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002665{
2666 unsigned long i;
2667 int ret = 1;
2668
2669 for (i = 0; i < HASH_BUCKETS; ++i) {
2670 struct obj_symbol *sym;
2671 for (sym = f->symtab[i]; sym; sym = sym->next)
2672 if (sym->secidx == SHN_UNDEF) {
2673 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2674 sym->secidx = SHN_ABS;
2675 sym->value = 0;
2676 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002677 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002678 ret = 0;
2679 }
2680 }
2681 }
2682
2683 return ret;
2684}
2685
Eric Andersen044228d2001-07-17 01:12:36 +00002686static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002687{
2688 struct common_entry {
2689 struct common_entry *next;
2690 struct obj_symbol *sym;
2691 } *common_head = NULL;
2692
2693 unsigned long i;
2694
2695 for (i = 0; i < HASH_BUCKETS; ++i) {
2696 struct obj_symbol *sym;
2697 for (sym = f->symtab[i]; sym; sym = sym->next)
2698 if (sym->secidx == SHN_COMMON) {
2699 /* Collect all COMMON symbols and sort them by size so as to
2700 minimize space wasted by alignment requirements. */
2701 {
2702 struct common_entry **p, *n;
2703 for (p = &common_head; *p; p = &(*p)->next)
2704 if (sym->size <= (*p)->sym->size)
2705 break;
2706
2707 n = alloca(sizeof(*n));
2708 n->next = *p;
2709 n->sym = sym;
2710 *p = n;
2711 }
2712 }
2713 }
2714
2715 for (i = 1; i < f->local_symtab_size; ++i) {
2716 struct obj_symbol *sym = f->local_symtab[i];
2717 if (sym && sym->secidx == SHN_COMMON) {
2718 struct common_entry **p, *n;
2719 for (p = &common_head; *p; p = &(*p)->next)
2720 if (sym == (*p)->sym)
2721 break;
2722 else if (sym->size < (*p)->sym->size) {
2723 n = alloca(sizeof(*n));
2724 n->next = *p;
2725 n->sym = sym;
2726 *p = n;
2727 break;
2728 }
2729 }
2730 }
2731
2732 if (common_head) {
2733 /* Find the bss section. */
2734 for (i = 0; i < f->header.e_shnum; ++i)
2735 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2736 break;
2737
2738 /* If for some reason there hadn't been one, create one. */
2739 if (i == f->header.e_shnum) {
2740 struct obj_section *sec;
2741
2742 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2743 f->sections[i] = sec = arch_new_section();
2744 f->header.e_shnum = i + 1;
2745
2746 memset(sec, 0, sizeof(*sec));
2747 sec->header.sh_type = SHT_PROGBITS;
2748 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2749 sec->name = ".bss";
2750 sec->idx = i;
2751 }
2752
2753 /* Allocate the COMMONS. */
2754 {
2755 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2756 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2757 struct common_entry *c;
2758
2759 for (c = common_head; c; c = c->next) {
2760 ElfW(Addr) align = c->sym->value;
2761
2762 if (align > max_align)
2763 max_align = align;
2764 if (bss_size & (align - 1))
2765 bss_size = (bss_size | (align - 1)) + 1;
2766
2767 c->sym->secidx = i;
2768 c->sym->value = bss_size;
2769
2770 bss_size += c->sym->size;
2771 }
2772
2773 f->sections[i]->header.sh_size = bss_size;
2774 f->sections[i]->header.sh_addralign = max_align;
2775 }
2776 }
2777
2778 /* For the sake of patch relocation and parameter initialization,
2779 allocate zeroed data for NOBITS sections now. Note that after
2780 this we cannot assume NOBITS are really empty. */
2781 for (i = 0; i < f->header.e_shnum; ++i) {
2782 struct obj_section *s = f->sections[i];
2783 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002784 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002785 s->contents = memset(xmalloc(s->header.sh_size),
2786 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002787 else
2788 s->contents = NULL;
2789
Eric Andersen9f16d612000-06-12 23:11:16 +00002790 s->header.sh_type = SHT_PROGBITS;
2791 }
2792 }
2793}
2794
Eric Andersen044228d2001-07-17 01:12:36 +00002795static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002796{
2797 unsigned long dot = 0;
2798 struct obj_section *sec;
2799
2800 /* Finalize the positions of the sections relative to one another. */
2801
2802 for (sec = f->load_order; sec; sec = sec->load_next) {
2803 ElfW(Addr) align;
2804
2805 align = sec->header.sh_addralign;
2806 if (align && (dot & (align - 1)))
2807 dot = (dot | (align - 1)) + 1;
2808
2809 sec->header.sh_addr = dot;
2810 dot += sec->header.sh_size;
2811 }
2812
2813 return dot;
2814}
2815
Eric Andersen044228d2001-07-17 01:12:36 +00002816static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002817{
2818 int i, n = f->header.e_shnum;
2819 int ret = 1;
2820
2821 /* Finalize the addresses of the sections. */
2822
2823 f->baseaddr = base;
2824 for (i = 0; i < n; ++i)
2825 f->sections[i]->header.sh_addr += base;
2826
2827 /* And iterate over all of the relocations. */
2828
2829 for (i = 0; i < n; ++i) {
2830 struct obj_section *relsec, *symsec, *targsec, *strsec;
2831 ElfW(RelM) * rel, *relend;
2832 ElfW(Sym) * symtab;
2833 const char *strtab;
2834
2835 relsec = f->sections[i];
2836 if (relsec->header.sh_type != SHT_RELM)
2837 continue;
2838
2839 symsec = f->sections[relsec->header.sh_link];
2840 targsec = f->sections[relsec->header.sh_info];
2841 strsec = f->sections[symsec->header.sh_link];
2842
2843 rel = (ElfW(RelM) *) relsec->contents;
2844 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2845 symtab = (ElfW(Sym) *) symsec->contents;
2846 strtab = (const char *) strsec->contents;
2847
2848 for (; rel < relend; ++rel) {
2849 ElfW(Addr) value = 0;
2850 struct obj_symbol *intsym = NULL;
2851 unsigned long symndx;
2852 ElfW(Sym) * extsym = 0;
2853 const char *errmsg;
2854
2855 /* Attempt to find a value to use for this relocation. */
2856
2857 symndx = ELFW(R_SYM) (rel->r_info);
2858 if (symndx) {
2859 /* Note we've already checked for undefined symbols. */
2860
2861 extsym = &symtab[symndx];
2862 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2863 /* Local symbols we look up in the local table to be sure
2864 we get the one that is really intended. */
2865 intsym = f->local_symtab[symndx];
2866 } else {
2867 /* Others we look up in the hash table. */
2868 const char *name;
2869 if (extsym->st_name)
2870 name = strtab + extsym->st_name;
2871 else
2872 name = f->sections[extsym->st_shndx]->name;
2873 intsym = obj_find_symbol(f, name);
2874 }
2875
2876 value = obj_symbol_final_value(f, intsym);
2877 intsym->referenced = 1;
2878 }
2879#if SHT_RELM == SHT_RELA
2880#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2881 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2882 if (!extsym || !extsym->st_name ||
2883 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2884#endif
2885 value += rel->r_addend;
2886#endif
2887
2888 /* Do it! */
2889 switch (arch_apply_relocation
2890 (f, targsec, symsec, intsym, rel, value)) {
2891 case obj_reloc_ok:
2892 break;
2893
2894 case obj_reloc_overflow:
2895 errmsg = "Relocation overflow";
2896 goto bad_reloc;
2897 case obj_reloc_dangerous:
2898 errmsg = "Dangerous relocation";
2899 goto bad_reloc;
2900 case obj_reloc_unhandled:
2901 errmsg = "Unhandled relocation";
2902 bad_reloc:
2903 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002904 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002905 (long) ELFW(R_TYPE) (rel->r_info),
2906 strtab + extsym->st_name);
2907 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002908 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002909 (long) ELFW(R_TYPE) (rel->r_info));
2910 }
2911 ret = 0;
2912 break;
2913 }
2914 }
2915 }
2916
2917 /* Finally, take care of the patches. */
2918
2919 if (f->string_patches) {
2920 struct obj_string_patch *p;
2921 struct obj_section *strsec;
2922 ElfW(Addr) strsec_base;
2923 strsec = obj_find_section(f, ".kstrtab");
2924 strsec_base = strsec->header.sh_addr;
2925
2926 for (p = f->string_patches; p; p = p->next) {
2927 struct obj_section *targsec = f->sections[p->reloc_secidx];
2928 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2929 = strsec_base + p->string_offset;
2930 }
2931 }
2932
2933 if (f->symbol_patches) {
2934 struct obj_symbol_patch *p;
2935
2936 for (p = f->symbol_patches; p; p = p->next) {
2937 struct obj_section *targsec = f->sections[p->reloc_secidx];
2938 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2939 = obj_symbol_final_value(f, p->sym);
2940 }
2941 }
2942
2943 return ret;
2944}
2945
Eric Andersen044228d2001-07-17 01:12:36 +00002946static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002947{
2948 struct obj_section *sec;
2949 ElfW(Addr) base = f->baseaddr;
2950
2951 for (sec = f->load_order; sec; sec = sec->load_next) {
2952 char *secimg;
2953
Eric Andersen2bf658d2001-02-24 20:01:53 +00002954 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002955 continue;
2956
2957 secimg = image + (sec->header.sh_addr - base);
2958
2959 /* Note that we allocated data for NOBITS sections earlier. */
2960 memcpy(secimg, sec->contents, sec->header.sh_size);
2961 }
2962
2963 return 1;
2964}
2965
2966/*======================================================================*/
2967
Eric Andersen044228d2001-07-17 01:12:36 +00002968static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002969{
2970 struct obj_file *f;
2971 ElfW(Shdr) * section_headers;
2972 int shnum, i;
2973 char *shstrtab;
2974
2975 /* Read the file header. */
2976
2977 f = arch_new_file();
2978 memset(f, 0, sizeof(*f));
2979 f->symbol_cmp = strcmp;
2980 f->symbol_hash = obj_elf_hash;
2981 f->load_order_search_start = &f->load_order;
2982
2983 fseek(fp, 0, SEEK_SET);
2984 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002985 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002986 return NULL;
2987 }
2988
2989 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2990 || f->header.e_ident[EI_MAG1] != ELFMAG1
2991 || f->header.e_ident[EI_MAG2] != ELFMAG2
2992 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002993 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002994 return NULL;
2995 }
2996 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2997 || f->header.e_ident[EI_DATA] != ELFDATAM
2998 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2999 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003000 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003001 return NULL;
3002 }
3003 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003004 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003005 return NULL;
3006 }
3007
3008 /* Read the section headers. */
3009
3010 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003011 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003012 (unsigned long) f->header.e_shentsize,
3013 (unsigned long) sizeof(ElfW(Shdr)));
3014 return NULL;
3015 }
3016
3017 shnum = f->header.e_shnum;
3018 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3019 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3020
3021 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3022 fseek(fp, f->header.e_shoff, SEEK_SET);
3023 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003024 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003025 return NULL;
3026 }
3027
3028 /* Read the section data. */
3029
3030 for (i = 0; i < shnum; ++i) {
3031 struct obj_section *sec;
3032
3033 f->sections[i] = sec = arch_new_section();
3034 memset(sec, 0, sizeof(*sec));
3035
3036 sec->header = section_headers[i];
3037 sec->idx = i;
3038
Eric Andersen2bf658d2001-02-24 20:01:53 +00003039 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003040 case SHT_NULL:
3041 case SHT_NOTE:
3042 case SHT_NOBITS:
3043 /* ignore */
3044 break;
3045
3046 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003047#if LOADBITS
3048 if (!loadprogbits) {
3049 sec->contents = NULL;
3050 break;
3051 }
3052#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003053 case SHT_SYMTAB:
3054 case SHT_STRTAB:
3055 case SHT_RELM:
3056 if (sec->header.sh_size > 0) {
3057 sec->contents = xmalloc(sec->header.sh_size);
3058 fseek(fp, sec->header.sh_offset, SEEK_SET);
3059 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003060 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003061 return NULL;
3062 }
3063 } else {
3064 sec->contents = NULL;
3065 }
3066 break;
3067
3068#if SHT_RELM == SHT_REL
3069 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003070 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003071 return NULL;
3072#else
3073 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003074 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003075 return NULL;
3076#endif
3077
3078 default:
3079 if (sec->header.sh_type >= SHT_LOPROC) {
3080 /* Assume processor specific section types are debug
3081 info and can safely be ignored. If this is ever not
3082 the case (Hello MIPS?), don't put ifdefs here but
3083 create an arch_load_proc_section(). */
3084 break;
3085 }
3086
Matt Kraaidd19c692001-01-31 19:00:21 +00003087 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003088 (long) sec->header.sh_type);
3089 return NULL;
3090 }
3091 }
3092
3093 /* Do what sort of interpretation as needed by each section. */
3094
3095 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3096
3097 for (i = 0; i < shnum; ++i) {
3098 struct obj_section *sec = f->sections[i];
3099 sec->name = shstrtab + sec->header.sh_name;
3100 }
3101
3102 for (i = 0; i < shnum; ++i) {
3103 struct obj_section *sec = f->sections[i];
3104
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003105 /* .modinfo should be contents only but gcc has no attribute for that.
3106 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3107 */
3108 if (strcmp(sec->name, ".modinfo") == 0)
3109 sec->header.sh_flags &= ~SHF_ALLOC;
3110
Eric Andersen9f16d612000-06-12 23:11:16 +00003111 if (sec->header.sh_flags & SHF_ALLOC)
3112 obj_insert_section_load_order(f, sec);
3113
3114 switch (sec->header.sh_type) {
3115 case SHT_SYMTAB:
3116 {
3117 unsigned long nsym, j;
3118 char *strtab;
3119 ElfW(Sym) * sym;
3120
3121 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003122 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003123 (unsigned long) sec->header.sh_entsize,
3124 (unsigned long) sizeof(ElfW(Sym)));
3125 return NULL;
3126 }
3127
3128 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3129 strtab = f->sections[sec->header.sh_link]->contents;
3130 sym = (ElfW(Sym) *) sec->contents;
3131
3132 /* Allocate space for a table of local symbols. */
3133 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003134 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003135
3136 /* Insert all symbols into the hash table. */
3137 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3138 const char *name;
3139 if (sym->st_name)
3140 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003141 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003142 name = f->sections[sym->st_shndx]->name;
3143
3144 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3145 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003146 }
3147 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003148 break;
3149
3150 case SHT_RELM:
3151 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003152 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003153 (unsigned long) sec->header.sh_entsize,
3154 (unsigned long) sizeof(ElfW(RelM)));
3155 return NULL;
3156 }
3157 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003158 /* XXX Relocation code from modutils-2.3.19 is not here.
3159 * Why? That's about 20 lines of code from obj/obj_load.c,
3160 * which gets done in a second pass through the sections.
3161 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003162 }
3163 }
3164
3165 return f;
3166}
3167
Eric Andersen8ae319a2001-05-21 16:09:18 +00003168#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3169/*
3170 * load the unloaded sections directly into the memory allocated by
3171 * kernel for the module
3172 */
3173
Eric Andersen044228d2001-07-17 01:12:36 +00003174static int obj_load_progbits(FILE * fp, struct obj_file* f)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003175{
3176 char* imagebase = (char*) f->imagebase;
3177 ElfW(Addr) base = f->baseaddr;
3178 struct obj_section* sec;
3179
3180 for (sec = f->load_order; sec; sec = sec->load_next) {
3181
3182 /* section already loaded? */
3183 if (sec->contents != NULL)
3184 continue;
3185
3186 if (sec->header.sh_size == 0)
3187 continue;
3188
3189 sec->contents = imagebase + (sec->header.sh_addr - base);
3190 fseek(fp, sec->header.sh_offset, SEEK_SET);
3191 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3192 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3193 return 0;
3194 }
3195
3196 }
3197 return 1;
3198}
3199#endif
3200
Eric Andersen9f16d612000-06-12 23:11:16 +00003201static void hide_special_symbols(struct obj_file *f)
3202{
3203 static const char *const specials[] = {
3204 "cleanup_module",
3205 "init_module",
3206 "kernel_version",
3207 NULL
3208 };
3209
3210 struct obj_symbol *sym;
3211 const char *const *p;
3212
3213 for (p = specials; *p; ++p)
3214 if ((sym = obj_find_symbol(f, *p)) != NULL)
3215 sym->info =
3216 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3217}
3218
3219
3220
3221extern int insmod_main( int argc, char **argv)
3222{
Eric Andersena18aaf12001-01-24 19:07:09 +00003223 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003224 int k_crcs;
3225 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003226 int len;
3227 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003228 unsigned long m_size;
3229 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003230 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003231 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003232 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003233 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003234 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003235 int m_has_modinfo;
3236#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3237 int k_version;
3238 char k_strversion[STRVERSIONLEN];
3239 char m_strversion[STRVERSIONLEN];
3240 int m_version;
3241 int m_crcs;
3242#endif
3243
Erik Andersene49d5ec2000-02-08 19:58:47 +00003244 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003245 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003246 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003247 case 'f': /* force loading */
3248 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003249 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 case 'k': /* module loaded by kerneld, auto-cleanable */
3251 flag_autoclean = 1;
3252 break;
3253 case 'v': /* verbose output */
3254 flag_verbose = 1;
3255 break;
3256 case 'x': /* do not export externs */
3257 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003258 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003259 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003260 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003261 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003262 case 'L': /* Stub warning */
3263 /* This is needed for compatibility with modprobe.
3264 * In theory, this does locking, but we don't do
3265 * that. So be careful and plan your life around not
3266 * loading the same module 50 times concurrently. */
3267 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003268 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003269 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003270 }
Erik Andersend387d011999-12-21 02:55:11 +00003271 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003272
3273 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003274 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003275 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003276
Erik Andersene49d5ec2000-02-08 19:58:47 +00003277 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003278 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003279 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003280 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003281 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003282 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003283 len = strlen(tmp);
3284
3285 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3286 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003287 memcpy(m_fullName, tmp, len);
3288 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003289 if (*m_name == '\0') {
3290 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003291 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003292 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003293
Eric Andersen14d35432001-05-14 17:07:32 +00003294 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003295 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3296 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003297 struct utsname myuname;
3298
3299 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3300 * but do not error out yet if we fail to find it... */
3301 if (uname(&myuname) == 0) {
3302 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003303 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003304 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3305 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003306 /* Jump through hoops in case /lib/modules/`uname -r`
3307 * is a symlink. We do not want recursive_action to
3308 * follow symlinks, but we do want to follow the
3309 * /lib/modules/`uname -r` dir, So resolve it ourselves
3310 * if it is a link... */
3311 if (realpath (module_dir, real_module_dir) == NULL)
3312 strcpy(real_module_dir, module_dir);
3313 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003314 check_module_name_match, 0, m_fullName);
3315 }
3316
3317 /* Check if we have found anything yet */
3318 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003319 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003320 char module_dir[FILENAME_MAX];
3321 if (realpath (_PATH_MODULES, module_dir) == NULL)
3322 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003323 /* No module found under /lib/modules/`uname -r`, this
3324 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003325 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003326 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003327 {
Eric Andersen14d35432001-05-14 17:07:32 +00003328 if (m_filename[0] == '\0'
3329 || ((fp = fopen(m_filename, "r")) == NULL))
3330 {
3331 error_msg("%s: no module by that name found", m_fullName);
3332 return EXIT_FAILURE;
3333 }
3334 } else
3335 error_msg_and_die("%s: no module by that name found", m_fullName);
3336 }
3337 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003338 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003339
Eric Andersen14d35432001-05-14 17:07:32 +00003340 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003341
Eric Andersen8ae319a2001-05-21 16:09:18 +00003342 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003343 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003344
Eric Andersen9f16d612000-06-12 23:11:16 +00003345 if (get_modinfo_value(f, "kernel_version") == NULL)
3346 m_has_modinfo = 0;
3347 else
3348 m_has_modinfo = 1;
3349
3350#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3351 /* Version correspondence? */
3352
3353 k_version = get_kernel_version(k_strversion);
3354 if (m_has_modinfo) {
3355 m_version = new_get_module_version(f, m_strversion);
3356 } else {
3357 m_version = old_get_module_version(f, m_strversion);
3358 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003359 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003360 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003361 goto out;
3362 }
3363 }
3364
3365 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3366 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003367 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003368 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003369 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003370 m_filename, m_strversion, k_strversion);
3371 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003372 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003373 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003374 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003375 m_filename, m_strversion, k_strversion);
3376 goto out;
3377 }
3378 }
3379 k_crcs = 0;
3380#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3381
3382 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3383
3384 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003385#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003386 if (!new_get_kernel_symbols())
3387 goto out;
3388 k_crcs = new_is_kernel_checksummed();
3389#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003390 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003391 goto out;
3392#endif
3393 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003394#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003395 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 goto out;
3397 k_crcs = old_is_kernel_checksummed();
3398#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003399 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003400 goto out;
3401#endif
3402 }
3403
3404#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3405 if (m_has_modinfo)
3406 m_crcs = new_is_module_checksummed(f);
3407 else
3408 m_crcs = old_is_module_checksummed(f);
3409
3410 if (m_crcs != k_crcs)
3411 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3412#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3413
Erik Andersene49d5ec2000-02-08 19:58:47 +00003414 /* Let the module know about the kernel symbols. */
3415 add_kernel_symbols(f);
3416
Eric Andersen9f16d612000-06-12 23:11:16 +00003417 /* Allocate common symbols, symbol tables, and string tables. */
3418
3419 if (k_new_syscalls
3420 ? !new_create_this_module(f, m_name)
3421 : !old_create_mod_use_count(f))
3422 {
3423 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003424 }
3425
Eric Andersen9f16d612000-06-12 23:11:16 +00003426 if (!obj_check_undefineds(f)) {
3427 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003428 }
3429 obj_allocate_commons(f);
3430
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003431 /* done with the module name, on to the optional var=value arguments */
3432 ++optind;
3433
Eric Andersen9f16d612000-06-12 23:11:16 +00003434 if (optind < argc) {
3435 if (m_has_modinfo
3436 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3437 : !old_process_module_arguments(f, argc - optind, argv + optind))
3438 {
3439 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003440 }
3441 }
3442
Eric Andersen9f16d612000-06-12 23:11:16 +00003443 arch_create_got(f);
3444 hide_special_symbols(f);
3445
3446 if (k_new_syscalls)
3447 new_create_module_ksymtab(f);
3448
Erik Andersene49d5ec2000-02-08 19:58:47 +00003449 /* Find current size of the module */
3450 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003451
3452
Erik Andersene49d5ec2000-02-08 19:58:47 +00003453 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003454 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003455 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003456 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003457 goto out;
3458 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003459 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003460 m_size);
3461 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003462 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003463 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003464 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003465 }
Erik Andersend387d011999-12-21 02:55:11 +00003466
Eric Andersen8ae319a2001-05-21 16:09:18 +00003467#if !LOADBITS
3468 /*
3469 * the PROGBITS section was not loaded by the obj_load
3470 * now we can load them directly into the kernel memory
3471 */
3472 // f->imagebase = (char*) m_addr;
3473 f->imagebase = (ElfW(Addr)) m_addr;
3474 if (!obj_load_progbits(fp, f)) {
3475 delete_module(m_name);
3476 goto out;
3477 }
3478#endif
3479
Eric Andersen9f16d612000-06-12 23:11:16 +00003480 if (!obj_relocate(f, m_addr)) {
3481 delete_module(m_name);
3482 goto out;
3483 }
Erik Andersend387d011999-12-21 02:55:11 +00003484
Eric Andersen9f16d612000-06-12 23:11:16 +00003485 if (k_new_syscalls
3486 ? !new_init_module(m_name, f, m_size)
3487 : !old_init_module(m_name, f, m_size))
3488 {
3489 delete_module(m_name);
3490 goto out;
3491 }
3492
Matt Kraai3e856ce2000-12-01 02:55:13 +00003493 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003494
3495out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003496 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003497 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003498}