blob: 50f272edb4602b67bfd90d0f9abfb548d1998a35 [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
4 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00005 * Copyright (C) 1999,2000,2001 by Lineo, inc.
Eric Andersen9f16d612000-06-12 23:11:16 +00006 * Written by Erik Andersen <andersen@lineo.com>
7 * and Ron Alder <alder@lineo.com>
8 *
Eric Andersenfe4208f2000-09-24 03:44:29 +00009 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000010 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
11 *
12 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
13 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
14 * very minor changes required to also work with StrongArm and presumably
15 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000017 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
18 * PowerPC specific code stolen from modutils-2.3.16,
19 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
20 * I've only tested the code on mpc8xx platforms in big-endian mode.
21 * Did some cleanup and added BB_USE_xxx_ENTRIES...
22 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000023 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
24 * based on modutils-2.4.2
25 * MIPS specific support for Elf loading and relocation.
26 * Copyright 1996, 1997 Linux International.
27 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
28 *
Eric Andersen9f16d612000-06-12 23:11:16 +000029 * Based almost entirely on the Linux modutils-2.3.11 implementation.
30 * Copyright 1996, 1997 Linux International.
31 * New implementation contributed by Richard Henderson <rth@tamu.edu>
32 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
33 * Restructured (and partly rewritten) by:
34 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000035 *
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation; either version 2 of the License, or
39 * (at your option) any later version.
40 *
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software
48 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
49 *
50 */
51
Erik Andersen02104321999-12-17 18:57:34 +000052#include <stdlib.h>
53#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000054#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000055#include <errno.h>
56#include <unistd.h>
57#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000058#include <ctype.h>
59#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000060#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000061#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000062#include <sys/utsname.h>
Eric Andersened3ef502001-01-27 08:24:39 +000063#include <sys/syscall.h>
64#include <linux/unistd.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000065#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000066
Eric Andersen90fe7fe2001-02-20 20:47:08 +000067#if defined(__powerpc__)
68#define BB_USE_PLT_ENTRIES
69#define BB_PLT_ENTRY_SIZE 16
70#endif
71
72#if defined(__arm__)
73#define BB_USE_PLT_ENTRIES
74#define BB_PLT_ENTRY_SIZE 8
75#define BB_USE_GOT_ENTRIES
76#define BB_GOT_ENTRY_SIZE 8
77#endif
78
79#if defined(__sh__)
80#define BB_USE_GOT_ENTRIES
81#define BB_GOT_ENTRY_SIZE 4
82#endif
83
84#if defined(__i386__)
85#define BB_USE_GOT_ENTRIES
86#define BB_GOT_ENTRY_SIZE 4
87#endif
88
Eric Andersen2bf658d2001-02-24 20:01:53 +000089#if defined(__mips__)
90// neither used
91#endif
92
Eric Andersen9f16d612000-06-12 23:11:16 +000093//----------------------------------------------------------------------------
94//--------modutils module.h, lines 45-242
95//----------------------------------------------------------------------------
96
97/* Definitions for the Linux module syscall interface.
98 Copyright 1996, 1997 Linux International.
99
100 Contributed by Richard Henderson <rth@tamu.edu>
101
102 This file is part of the Linux modutils.
103
104 This program is free software; you can redistribute it and/or modify it
105 under the terms of the GNU General Public License as published by the
106 Free Software Foundation; either version 2 of the License, or (at your
107 option) any later version.
108
109 This program is distributed in the hope that it will be useful, but
110 WITHOUT ANY WARRANTY; without even the implied warranty of
111 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
112 General Public License for more details.
113
114 You should have received a copy of the GNU General Public License
115 along with this program; if not, write to the Free Software Foundation,
116 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
117
118
119#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000120static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000121
Eric Andersen2bf658d2001-02-24 20:01:53 +0000122#ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000123
124/* This file contains the structures used by the 2.0 and 2.1 kernels.
125 We do not use the kernel headers directly because we do not wish
126 to be dependant on a particular kernel version to compile insmod. */
127
128
129/*======================================================================*/
130/* The structures used by Linux 2.0. */
131
132/* The symbol format used by get_kernel_syms(2). */
133struct old_kernel_sym
134{
135 unsigned long value;
136 char name[60];
137};
138
139struct old_module_ref
140{
141 unsigned long module; /* kernel addresses */
142 unsigned long next;
143};
144
145struct old_module_symbol
146{
147 unsigned long addr;
148 unsigned long name;
149};
150
151struct old_symbol_table
152{
153 int size; /* total, including string table!!! */
154 int n_symbols;
155 int n_refs;
156 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
157 struct old_module_ref ref[0]; /* actual size defined by n_refs */
158};
159
160struct old_mod_routines
161{
162 unsigned long init;
163 unsigned long cleanup;
164};
165
166struct old_module
167{
168 unsigned long next;
169 unsigned long ref; /* the list of modules that refer to me */
170 unsigned long symtab;
171 unsigned long name;
172 int size; /* size of module in pages */
173 unsigned long addr; /* address of module */
174 int state;
175 unsigned long cleanup; /* cleanup routine */
176};
177
178/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000179static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000180
181int get_kernel_syms(struct old_kernel_sym *);
182int old_sys_init_module(const char *name, char *code, unsigned codesize,
183 struct old_mod_routines *, struct old_symbol_table *);
184
185/*======================================================================*/
186/* For sizeof() which are related to the module platform and not to the
187 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
188
189#define tgt_sizeof_char sizeof(char)
190#define tgt_sizeof_short sizeof(short)
191#define tgt_sizeof_int sizeof(int)
192#define tgt_sizeof_long sizeof(long)
193#define tgt_sizeof_char_p sizeof(char *)
194#define tgt_sizeof_void_p sizeof(void *)
195#define tgt_long long
196
197#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
198#undef tgt_sizeof_long
199#undef tgt_sizeof_char_p
200#undef tgt_sizeof_void_p
201#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000202static const int tgt_sizeof_long = 8;
203static const int tgt_sizeof_char_p = 8;
204static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000205#define tgt_long long long
206#endif
207
208/*======================================================================*/
209/* The structures used in Linux 2.1. */
210
211/* Note: new_module_symbol does not use tgt_long intentionally */
212struct new_module_symbol
213{
214 unsigned long value;
215 unsigned long name;
216};
217
218struct new_module_persist;
219
220struct new_module_ref
221{
222 unsigned tgt_long dep; /* kernel addresses */
223 unsigned tgt_long ref;
224 unsigned tgt_long next_ref;
225};
226
227struct new_module
228{
229 unsigned tgt_long size_of_struct; /* == sizeof(module) */
230 unsigned tgt_long next;
231 unsigned tgt_long name;
232 unsigned tgt_long size;
233
234 tgt_long usecount;
235 unsigned tgt_long flags; /* AUTOCLEAN et al */
236
237 unsigned nsyms;
238 unsigned ndeps;
239
240 unsigned tgt_long syms;
241 unsigned tgt_long deps;
242 unsigned tgt_long refs;
243 unsigned tgt_long init;
244 unsigned tgt_long cleanup;
245 unsigned tgt_long ex_table_start;
246 unsigned tgt_long ex_table_end;
247#ifdef __alpha__
248 unsigned tgt_long gp;
249#endif
250 /* Everything after here is extension. */
251 unsigned tgt_long persist_start;
252 unsigned tgt_long persist_end;
253 unsigned tgt_long can_unload;
254 unsigned tgt_long runsize;
255};
256
257struct new_module_info
258{
259 unsigned long addr;
260 unsigned long size;
261 unsigned long flags;
262 long usecount;
263};
264
265/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000266static const int NEW_MOD_RUNNING = 1;
267static const int NEW_MOD_DELETED = 2;
268static const int NEW_MOD_AUTOCLEAN = 4;
269static const int NEW_MOD_VISITED = 8;
270static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000271
272int new_sys_init_module(const char *name, const struct new_module *);
273int query_module(const char *name, int which, void *buf, size_t bufsize,
274 size_t *ret);
275
276/* Values for query_module's which. */
277
Mark Whitley59ab0252001-01-23 22:30:04 +0000278static const int QM_MODULES = 1;
279static const int QM_DEPS = 2;
280static const int QM_REFS = 3;
281static const int QM_SYMBOLS = 4;
282static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000283
284/*======================================================================*/
285/* The system calls unchanged between 2.0 and 2.1. */
286
287unsigned long create_module(const char *, size_t);
288int delete_module(const char *);
289
290
291#endif /* module.h */
292
293//----------------------------------------------------------------------------
294//--------end of modutils module.h
295//----------------------------------------------------------------------------
296
297
298
299//----------------------------------------------------------------------------
300//--------modutils obj.h, lines 253-462
301//----------------------------------------------------------------------------
302
303/* Elf object file loading and relocation routines.
304 Copyright 1996, 1997 Linux International.
305
306 Contributed by Richard Henderson <rth@tamu.edu>
307
308 This file is part of the Linux modutils.
309
310 This program is free software; you can redistribute it and/or modify it
311 under the terms of the GNU General Public License as published by the
312 Free Software Foundation; either version 2 of the License, or (at your
313 option) any later version.
314
315 This program is distributed in the hope that it will be useful, but
316 WITHOUT ANY WARRANTY; without even the implied warranty of
317 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
318 General Public License for more details.
319
320 You should have received a copy of the GNU General Public License
321 along with this program; if not, write to the Free Software Foundation,
322 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
323
324
325#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000326static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000327
Eric Andersen2bf658d2001-02-24 20:01:53 +0000328#ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000329
330/* The relocatable object is manipulated using elfin types. */
331
332#include <stdio.h>
333#include <elf.h>
334
335
336/* Machine-specific elf macros for i386 et al. */
337
Eric Andersenfe4208f2000-09-24 03:44:29 +0000338/* the SH changes have only been tested on the SH4 in =little endian= mode */
339/* I'm not sure about big endian, so let's warn: */
340
341#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
342#error insmod.c may require changes for use on big endian SH4/SH3
343#endif
344
345/* it may or may not work on the SH1/SH2... So let's error on those
346 also */
347#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
348#error insmod.c may require changes for non-SH3/SH4 use
349#endif
350
Eric Andersen9f16d612000-06-12 23:11:16 +0000351#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000352
353#if defined(__sh__)
354
355#define MATCH_MACHINE(x) (x == EM_SH)
356#define SHT_RELM SHT_RELA
357#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000358#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000359
Eric Andersen21adca72000-12-06 18:18:26 +0000360#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000361
Eric Andersen21adca72000-12-06 18:18:26 +0000362#define MATCH_MACHINE(x) (x == EM_ARM)
363#define SHT_RELM SHT_REL
364#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000365#define ELFDATAM ELFDATA2LSB
366
367#elif defined(__powerpc__)
368
369#define MATCH_MACHINE(x) (x == EM_PPC)
370#define SHT_RELM SHT_RELA
371#define Elf32_RelM Elf32_Rela
372#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000373
Eric Andersen2bf658d2001-02-24 20:01:53 +0000374#elif defined(__mips__)
375
376#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
377#define SHT_RELM SHT_REL
378#define Elf32_RelM Elf32_Rel
379#ifdef __MIPSEB__
380#define ELFDATAM ELFDATA2MSB
381#endif
382#ifdef __MIPSEL__
383#define ELFDATAM ELFDATA2LSB
384#endif
385
Eric Andersen21adca72000-12-06 18:18:26 +0000386#elif defined(__i386__)
387
388/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000389/* this is the previous behavior, but it does result in
390 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000391#ifndef EM_486
392#define MATCH_MACHINE(x) (x == EM_386)
393#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000394#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000395#endif
396
Eric Andersen9f16d612000-06-12 23:11:16 +0000397#define SHT_RELM SHT_REL
398#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000399#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000400
Eric Andersen21adca72000-12-06 18:18:26 +0000401#else
Eric Andersend5cad142001-01-26 02:23:57 +0000402#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000403#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000404
405#ifndef ElfW
406# if ELFCLASSM == ELFCLASS32
407# define ElfW(x) Elf32_ ## x
408# define ELFW(x) ELF32_ ## x
409# else
410# define ElfW(x) Elf64_ ## x
411# define ELFW(x) ELF64_ ## x
412# endif
413#endif
414
415/* For some reason this is missing from libc5. */
416#ifndef ELF32_ST_INFO
417# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
418#endif
419
420#ifndef ELF64_ST_INFO
421# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
422#endif
423
424struct obj_string_patch;
425struct obj_symbol_patch;
426
427struct obj_section
428{
429 ElfW(Shdr) header;
430 const char *name;
431 char *contents;
432 struct obj_section *load_next;
433 int idx;
434};
435
436struct obj_symbol
437{
438 struct obj_symbol *next; /* hash table link */
439 const char *name;
440 unsigned long value;
441 unsigned long size;
442 int secidx; /* the defining section index/module */
443 int info;
444 int ksymidx; /* for export to the kernel symtab */
445 int referenced; /* actually used in the link */
446};
447
448/* Hardcode the hash table size. We shouldn't be needing so many
449 symbols that we begin to degrade performance, and we get a big win
450 by giving the compiler a constant divisor. */
451
452#define HASH_BUCKETS 521
453
454struct obj_file
455{
456 ElfW(Ehdr) header;
457 ElfW(Addr) baseaddr;
458 struct obj_section **sections;
459 struct obj_section *load_order;
460 struct obj_section **load_order_search_start;
461 struct obj_string_patch *string_patches;
462 struct obj_symbol_patch *symbol_patches;
463 int (*symbol_cmp)(const char *, const char *);
464 unsigned long (*symbol_hash)(const char *);
465 unsigned long local_symtab_size;
466 struct obj_symbol **local_symtab;
467 struct obj_symbol *symtab[HASH_BUCKETS];
468};
469
470enum obj_reloc
471{
472 obj_reloc_ok,
473 obj_reloc_overflow,
474 obj_reloc_dangerous,
475 obj_reloc_unhandled
476};
477
478struct obj_string_patch
479{
480 struct obj_string_patch *next;
481 int reloc_secidx;
482 ElfW(Addr) reloc_offset;
483 ElfW(Addr) string_offset;
484};
485
486struct obj_symbol_patch
487{
488 struct obj_symbol_patch *next;
489 int reloc_secidx;
490 ElfW(Addr) reloc_offset;
491 struct obj_symbol *sym;
492};
493
494
495/* Generic object manipulation routines. */
496
497unsigned long obj_elf_hash(const char *);
498
499unsigned long obj_elf_hash_n(const char *, unsigned long len);
500
501struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
502 unsigned long symidx, int info, int secidx,
503 ElfW(Addr) value, unsigned long size);
504
505struct obj_symbol *obj_find_symbol (struct obj_file *f,
506 const char *name);
507
508ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
509 struct obj_symbol *sym);
510
511void obj_set_symbol_compare(struct obj_file *f,
512 int (*cmp)(const char *, const char *),
513 unsigned long (*hash)(const char *));
514
515struct obj_section *obj_find_section (struct obj_file *f,
516 const char *name);
517
518void obj_insert_section_load_order (struct obj_file *f,
519 struct obj_section *sec);
520
521struct obj_section *obj_create_alloced_section (struct obj_file *f,
522 const char *name,
523 unsigned long align,
524 unsigned long size);
525
526struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
527 const char *name,
528 unsigned long align,
529 unsigned long size);
530
531void *obj_extend_section (struct obj_section *sec, unsigned long more);
532
533int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
534 const char *string);
535
536int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
537 struct obj_symbol *sym);
538
539int obj_check_undefineds(struct obj_file *f);
540
541void obj_allocate_commons(struct obj_file *f);
542
543unsigned long obj_load_size (struct obj_file *f);
544
545int obj_relocate (struct obj_file *f, ElfW(Addr) base);
546
547struct obj_file *obj_load(FILE *f);
548
549int obj_create_image (struct obj_file *f, char *image);
550
551/* Architecture specific manipulation routines. */
552
553struct obj_file *arch_new_file (void);
554
555struct obj_section *arch_new_section (void);
556
557struct obj_symbol *arch_new_symbol (void);
558
559enum obj_reloc arch_apply_relocation (struct obj_file *f,
560 struct obj_section *targsec,
561 struct obj_section *symsec,
562 struct obj_symbol *sym,
563 ElfW(RelM) *rel, ElfW(Addr) value);
564
565int arch_create_got (struct obj_file *f);
566
567struct new_module;
568int arch_init_module (struct obj_file *f, struct new_module *);
569
570#endif /* obj.h */
571//----------------------------------------------------------------------------
572//--------end of modutils obj.h
573//----------------------------------------------------------------------------
574
575
576
577
Erik Andersen02104321999-12-17 18:57:34 +0000578
Erik Andersend387d011999-12-21 02:55:11 +0000579#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000580static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000581
Eric Andersen9f16d612000-06-12 23:11:16 +0000582/*======================================================================*/
583
584int flag_force_load = 0;
585int flag_autoclean = 0;
586int flag_verbose = 0;
587int flag_export = 1;
588
589
590/*======================================================================*/
591
Eric Andersenfe4208f2000-09-24 03:44:29 +0000592/* previously, these were named i386_* but since we could be
593 compiling for the sh, I've renamed them to the more general
594 arch_* These structures are the same between the x86 and SH,
595 and we can't support anything else right now anyway. In the
596 future maybe they should be #if defined'd */
597
Eric Andersen21adca72000-12-06 18:18:26 +0000598/* Done ;-) */
599
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000600
601
602#if defined(BB_USE_PLT_ENTRIES)
603struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000604{
605 int offset;
606 int allocated:1;
607 int inited:1; /* has been set up */
608};
609#endif
610
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000611#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000612struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000613 int offset;
614 unsigned offset_done:1;
615 unsigned reloc_done:1;
616};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000617#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000618
Eric Andersen2bf658d2001-02-24 20:01:53 +0000619#if defined(__mips__)
620struct mips_hi16
621{
622 struct mips_hi16 *next;
623 Elf32_Addr *addr;
624 Elf32_Addr value;
625};
626#endif
627
Eric Andersenfe4208f2000-09-24 03:44:29 +0000628struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000629 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000630#if defined(BB_USE_PLT_ENTRIES)
631 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000632#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000633#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000634 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000635#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000636#if defined(__mips__)
637 struct mips_hi16 *mips_hi16_list;
638#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000639};
640
Eric Andersenfe4208f2000-09-24 03:44:29 +0000641struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000642 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000643#if defined(BB_USE_PLT_ENTRIES)
644 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000645#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000646#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000647 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000648#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000649};
650
651
Eric Andersen9f16d612000-06-12 23:11:16 +0000652struct external_module {
653 const char *name;
654 ElfW(Addr) addr;
655 int used;
656 size_t nsyms;
657 struct new_module_symbol *syms;
658};
659
660struct new_module_symbol *ksyms;
661size_t nksyms;
662
663struct external_module *ext_modules;
664int n_ext_modules;
665int n_ext_modules_used;
666
Erik Andersend387d011999-12-21 02:55:11 +0000667
668
Erik Andersen02104321999-12-17 18:57:34 +0000669/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000670#define __NR_new_sys_init_module __NR_init_module
671_syscall2(int, new_sys_init_module, const char *, name,
672 const struct new_module *, info)
673#define __NR_old_sys_init_module __NR_init_module
674_syscall5(int, old_sys_init_module, const char *, name, char *, code,
675 unsigned, codesize, struct old_mod_routines *, routines,
676 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000677#ifndef BB_RMMOD
678_syscall1(int, delete_module, const char *, name)
679#else
680extern int delete_module(const char *);
681#endif
682
Eric Andersenfe4208f2000-09-24 03:44:29 +0000683/* This is kind of troublesome. See, we don't actually support
684 the m68k or the arm the same way we support i386 and (now)
685 sh. In doing my SH patch, I just assumed that whatever works
686 for i386 also works for m68k and arm since currently insmod.c
687 does nothing special for them. If this isn't true, the below
688 line is rather misleading IMHO, and someone should either
689 change it or add more proper architecture-dependent support
690 for these boys.
691
692 -- Bryan Rittmeyer <bryan@ixiacom.com> */
693
Eric Andersenf5d5e772001-01-24 23:34:48 +0000694#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen21adca72000-12-06 18:18:26 +0000695_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
696#endif
697
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000698#if defined(__i386__) || defined(__m68k__) || defined(__arm__) \
699 || defined(__powerpc__)
Erik Andersen02104321999-12-17 18:57:34 +0000700/* Jump through hoops to fixup error return codes */
701#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000702static inline _syscall2(long, _create_module, const char *, name, size_t,
703 size)
Erik Andersen02104321999-12-17 18:57:34 +0000704unsigned long create_module(const char *name, size_t size)
705{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000706 long ret = _create_module(name, size);
707
708 if (ret == -1 && errno > 125) {
709 ret = -errno;
710 errno = 0;
711 }
712 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000713}
714#else
715_syscall2(unsigned long, create_module, const char *, name, size_t, size)
716#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000717static char m_filename[BUFSIZ + 1] = "\0";
718static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000719
Eric Andersen9f16d612000-06-12 23:11:16 +0000720/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000721
Eric Andersen9f16d612000-06-12 23:11:16 +0000722
723static int findNamedModule(const char *fileName, struct stat *statbuf,
724 void *userDate)
725{
726 char *fullName = (char *) userDate;
727
728
729 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000730 return (FALSE);
731 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000732 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000733
734 if (tmp == NULL)
735 tmp = (char *) fileName;
736 else
737 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000738 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000739 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000740 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000741 return (FALSE);
742 }
Erik Andersend387d011999-12-21 02:55:11 +0000743 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000744 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000745}
746
Erik Andersen02104321999-12-17 18:57:34 +0000747
Eric Andersen9f16d612000-06-12 23:11:16 +0000748/*======================================================================*/
749
750struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000751{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000752 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000753 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000754
755#if defined(BB_USE_PLT_ENTRIES)
756 f->plt = NULL;
757#endif
758#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000759 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000760#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000761#if defined(__mips__)
762 f->mips_hi16_list = NULL;
763#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000764
Eric Andersen9f16d612000-06-12 23:11:16 +0000765 return &f->root;
766}
767
768struct obj_section *arch_new_section(void)
769{
770 return xmalloc(sizeof(struct obj_section));
771}
772
773struct obj_symbol *arch_new_symbol(void)
774{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000776 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000777
778#if defined(BB_USE_PLT_ENTRIES)
779 memset(&sym->pltent, 0, sizeof(sym->pltent));
780#endif
781#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000782 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000783#endif
784
Eric Andersen9f16d612000-06-12 23:11:16 +0000785 return &sym->root;
786}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000787
Eric Andersen9f16d612000-06-12 23:11:16 +0000788enum obj_reloc
789arch_apply_relocation(struct obj_file *f,
790 struct obj_section *targsec,
791 struct obj_section *symsec,
792 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000793 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000794{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000795 struct arch_file *ifile = (struct arch_file *) f;
796 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000797
Eric Andersen21adca72000-12-06 18:18:26 +0000798 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
799 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000800#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000801 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000802#endif
803#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000804 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000805 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000806 unsigned long *ip;
807#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000808 enum obj_reloc ret = obj_reloc_ok;
809
810 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000811
812/* even though these constants seem to be the same for
813 the i386 and the sh, we "#if define" them for clarity
814 and in case that ever changes */
815#if defined(__sh__)
816 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000817#elif defined(__arm__)
818 case R_ARM_NONE:
819#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000820 case R_386_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000821#elif defined(__powerpc__)
822 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000823#elif defined(__mips__)
824 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000826 break;
827
Eric Andersenfe4208f2000-09-24 03:44:29 +0000828#if defined(__sh__)
829 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000830#elif defined(__arm__)
831 case R_ARM_ABS32:
832#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833 case R_386_32:
834#elif defined(__powerpc__)
835 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000836#elif defined(__mips__)
837 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000838#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000839 *loc += v;
840 break;
841
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000842#if defined(__powerpc__)
843 case R_PPC_ADDR16_HA:
844 *(unsigned short *)loc = (v + 0x8000) >> 16;
845 break;
846
847 case R_PPC_ADDR16_HI:
848 *(unsigned short *)loc = v >> 16;
849 break;
850
851 case R_PPC_ADDR16_LO:
852 *(unsigned short *)loc = v;
853 break;
854#endif
855
Eric Andersen2bf658d2001-02-24 20:01:53 +0000856#if defined(__mips__)
857 case R_MIPS_26:
858 if (v % 4)
859 ret = obj_reloc_dangerous;
860 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
861 ret = obj_reloc_overflow;
862 *loc =
863 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
864 0x03ffffff);
865 break;
866
867 case R_MIPS_HI16:
868 {
869 struct mips_hi16 *n;
870
871 /* We cannot relocate this one now because we don't know the value
872 of the carry we need to add. Save the information, and let LO16
873 do the actual relocation. */
874 n = (struct mips_hi16 *) xmalloc(sizeof *n);
875 n->addr = loc;
876 n->value = v;
877 n->next = ifile->mips_hi16_list;
878 ifile->mips_hi16_list = n;
879 break;
880 }
881
882 case R_MIPS_LO16:
883 {
884 unsigned long insnlo = *loc;
885 Elf32_Addr val, vallo;
886
887 /* Sign extend the addend we extract from the lo insn. */
888 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
889
890 if (ifile->mips_hi16_list != NULL) {
891 struct mips_hi16 *l;
892
893 l = ifile->mips_hi16_list;
894 while (l != NULL) {
895 struct mips_hi16 *next;
896 unsigned long insn;
897
898 /* The value for the HI16 had best be the same. */
899 assert(v == l->value);
900
901 /* Do the HI16 relocation. Note that we actually don't
902 need to know anything about the LO16 itself, except where
903 to find the low 16 bits of the addend needed by the LO16. */
904 insn = *l->addr;
905 val =
906 ((insn & 0xffff) << 16) +
907 vallo;
908 val += v;
909
910 /* Account for the sign extension that will happen in the
911 low bits. */
912 val =
913 ((val >> 16) +
914 ((val & 0x8000) !=
915 0)) & 0xffff;
916
917 insn = (insn & ~0xffff) | val;
918 *l->addr = insn;
919
920 next = l->next;
921 free(l);
922 l = next;
923 }
924
925 ifile->mips_hi16_list = NULL;
926 }
927
928 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
929 val = v + vallo;
930 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
931 *loc = insnlo;
932 break;
933 }
934#endif
935
Eric Andersen21adca72000-12-06 18:18:26 +0000936#if defined(__arm__)
937#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000938 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000939 *loc += v - dot;
940 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000941#elif defined(__i386__)
942 case R_386_PLT32:
943 case R_386_PC32:
944 *loc += v - dot;
945 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000946#elif defined(__powerpc__)
947 case R_PPC_REL32:
948 *loc = v - dot;
949 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000950#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000951
Eric Andersenfe4208f2000-09-24 03:44:29 +0000952#if defined(__sh__)
953 case R_SH_PLT32:
954 *loc = v - dot;
955 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000956#elif defined(__i386__)
957#endif
958
959#if defined(BB_USE_PLT_ENTRIES)
960
961#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000962 case R_ARM_PC24:
963 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000964#endif
965#if defined(__powerpc__)
966 case R_PPC_REL24:
967#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000968 /* find the plt entry and initialize it if necessary */
969 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000970
971 pe = (struct arch_plt_entry*) &isym->pltent;
972
Eric Andersen21adca72000-12-06 18:18:26 +0000973 if (! pe->inited) {
974 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000975
976 /* generate some machine code */
977
978#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000979 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
980 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000981#endif
982#if defined(__powerpc__)
983 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
984 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
985 ip[2] = 0x7d6903a6; /* mtctr r11 */
986 ip[3] = 0x4e800420; /* bctr */
987#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000988 pe->inited = 1;
989 }
990
991 /* relative distance to target */
992 v -= dot;
993 /* if the target is too far away.... */
994 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
995 /* go via the plt */
996 v = plt + pe->offset - dot;
997 }
998 if (v & 3)
999 ret = obj_reloc_dangerous;
1000
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001001 /* merge the offset into the instruction. */
1002#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001003 /* Convert to words. */
1004 v >>= 2;
1005
Eric Andersen21adca72000-12-06 18:18:26 +00001006 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001007#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001008#if defined(__powerpc__)
1009 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1010#endif
1011 break;
1012#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001013
Eric Andersen21adca72000-12-06 18:18:26 +00001014#if defined(__arm__)
1015#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001016 case R_SH_GLOB_DAT:
1017 case R_SH_JMP_SLOT:
1018 *loc = v;
1019 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001020#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001021 case R_386_GLOB_DAT:
1022 case R_386_JMP_SLOT:
1023 *loc = v;
1024 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001025#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001026
Eric Andersen21adca72000-12-06 18:18:26 +00001027#if defined(__arm__)
1028#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001029 case R_SH_RELATIVE:
1030 *loc += f->baseaddr + rel->r_addend;
1031 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001032#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001033 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001034 *loc += f->baseaddr;
1035 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001036#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001037
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001038#if defined(BB_USE_GOT_ENTRIES)
1039
Eric Andersenfe4208f2000-09-24 03:44:29 +00001040#if defined(__sh__)
1041 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001042#elif defined(__arm__)
1043 case R_ARM_GOTPC:
1044#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001045 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001046#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001047 assert(got != 0);
1048#if defined(__sh__)
1049 *loc += got - dot + rel->r_addend;;
1050#elif defined(__i386__) || defined(__arm__)
1051 *loc += got - dot;
1052#endif
1053 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001054
Eric Andersenfe4208f2000-09-24 03:44:29 +00001055#if defined(__sh__)
1056 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001057#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001058 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001059#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001060 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001061#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001062 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001063 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001064 if (!isym->gotent.reloc_done) {
1065 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001066 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001067 }
Eric Andersen21adca72000-12-06 18:18:26 +00001068 /* make the reloc with_respect_to_.got */
1069#if defined(__sh__)
1070 *loc += isym->gotent.offset + rel->r_addend;
1071#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001072 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001073#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001074 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001075
Eric Andersen21adca72000-12-06 18:18:26 +00001076 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001077#if defined(__sh__)
1078 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001079#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001080 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001081#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001082 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001083#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001084 assert(got != 0);
1085 *loc += v - got;
1086 break;
1087
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001088#endif /* BB_USE_GOT_ENTRIES */
1089
Eric Andersen9f16d612000-06-12 23:11:16 +00001090 default:
Eric Andersen21125542000-12-13 16:41:29 +00001091 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001092 ret = obj_reloc_unhandled;
1093 break;
1094 }
1095
1096 return ret;
1097}
1098
1099int arch_create_got(struct obj_file *f)
1100{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001101#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001102 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001103 int i;
1104#if defined(BB_USE_GOT_ENTRIES)
1105 int got_offset = 0, gotneeded = 0;
1106#endif
1107#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001108 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001109#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001110 struct obj_section *relsec, *symsec, *strsec;
1111 ElfW(RelM) *rel, *relend;
1112 ElfW(Sym) *symtab, *extsym;
1113 const char *strtab, *name;
1114 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001115
Eric Andersen21adca72000-12-06 18:18:26 +00001116 for (i = 0; i < f->header.e_shnum; ++i) {
1117 relsec = f->sections[i];
1118 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001119 continue;
1120
Eric Andersen21adca72000-12-06 18:18:26 +00001121 symsec = f->sections[relsec->header.sh_link];
1122 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001123
Eric Andersen21adca72000-12-06 18:18:26 +00001124 rel = (ElfW(RelM) *) relsec->contents;
1125 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1126 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001127 strtab = (const char *) strsec->contents;
1128
1129 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001130 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001131
1132 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001133#if defined(__arm__)
1134 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001135 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001136#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001137 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001138 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001139#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001140 case R_386_GOT32:
1141 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001142#endif
1143
1144#if defined(__powerpc__)
1145 case R_PPC_REL24:
1146 pltneeded = 1;
1147 break;
1148#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001149
1150#if defined(__arm__)
1151 case R_ARM_PC24:
1152 case R_ARM_PLT32:
1153 pltneeded = 1;
1154 break;
1155
1156 case R_ARM_GOTPC:
1157 case R_ARM_GOTOFF:
1158 gotneeded = 1;
1159 if (got_offset == 0)
1160 got_offset = 4;
1161#elif defined(__sh__)
1162 case R_SH_GOTPC:
1163 case R_SH_GOTOFF:
1164 gotneeded = 1;
1165#elif defined(__i386__)
1166 case R_386_GOTPC:
1167 case R_386_GOTOFF:
1168 gotneeded = 1;
1169#endif
1170
1171 default:
1172 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001173 }
1174
Eric Andersen21adca72000-12-06 18:18:26 +00001175 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001176 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001177 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001178 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001179 }
1180 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001181#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001182 if (!intsym->gotent.offset_done) {
1183 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001184 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001185 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001186 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001187#endif
1188#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001189 if (pltneeded && intsym->pltent.allocated == 0) {
1190 intsym->pltent.allocated = 1;
1191 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001192 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001193 intsym->pltent.inited = 0;
1194 pltneeded = 0;
1195 }
1196#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001197 }
1198 }
Eric Andersen21adca72000-12-06 18:18:26 +00001199
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001200#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001201 if (got_offset) {
1202 struct obj_section* relsec = obj_find_section(f, ".got");
1203
1204 if (relsec) {
1205 obj_extend_section(relsec, got_offset);
1206 } else {
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001207 relsec = obj_create_alloced_section(f, ".got",
1208 BB_GOT_ENTRY_SIZE,
1209 got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001210 assert(relsec);
1211 }
1212
1213 ifile->got = relsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001214 }
Eric Andersen21adca72000-12-06 18:18:26 +00001215#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001216
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001217#if defined(BB_USE_PLT_ENTRIES)
1218 if (plt_offset)
1219 ifile->plt = obj_create_alloced_section(f, ".plt",
1220 BB_PLT_ENTRY_SIZE,
1221 plt_offset);
1222#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001223#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001224 return 1;
1225}
1226
1227int arch_init_module(struct obj_file *f, struct new_module *mod)
1228{
1229 return 1;
1230}
1231
1232
1233/*======================================================================*/
1234
1235/* Standard ELF hash function. */
1236inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1237{
1238 unsigned long h = 0;
1239 unsigned long g;
1240 unsigned char ch;
1241
1242 while (n > 0) {
1243 ch = *name++;
1244 h = (h << 4) + ch;
1245 if ((g = (h & 0xf0000000)) != 0) {
1246 h ^= g >> 24;
1247 h &= ~g;
1248 }
1249 n--;
1250 }
1251 return h;
1252}
1253
1254unsigned long obj_elf_hash(const char *name)
1255{
1256 return obj_elf_hash_n(name, strlen(name));
1257}
1258
1259#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1260/* Get the kernel version in the canonical integer form. */
1261
1262static int get_kernel_version(char str[STRVERSIONLEN])
1263{
1264 struct utsname uts_info;
1265 char *p, *q;
1266 int a, b, c;
1267
1268 if (uname(&uts_info) < 0)
1269 return -1;
1270 strncpy(str, uts_info.release, STRVERSIONLEN);
1271 p = uts_info.release;
1272
1273 a = strtoul(p, &p, 10);
1274 if (*p != '.')
1275 return -1;
1276 b = strtoul(p + 1, &p, 10);
1277 if (*p != '.')
1278 return -1;
1279 c = strtoul(p + 1, &q, 10);
1280 if (p + 1 == q)
1281 return -1;
1282
1283 return a << 16 | b << 8 | c;
1284}
1285
1286/* String comparison for non-co-versioned kernel and module. */
1287
1288static int ncv_strcmp(const char *a, const char *b)
1289{
1290 size_t alen = strlen(a), blen = strlen(b);
1291
1292 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1293 return strncmp(a, b, alen);
1294 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1295 return strncmp(a, b, blen);
1296 else
1297 return strcmp(a, b);
1298}
1299
1300/* String hashing for non-co-versioned kernel and module. Here
1301 we are simply forced to drop the crc from the hash. */
1302
1303static unsigned long ncv_symbol_hash(const char *str)
1304{
1305 size_t len = strlen(str);
1306 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1307 len -= 10;
1308 return obj_elf_hash_n(str, len);
1309}
1310
1311void
1312obj_set_symbol_compare(struct obj_file *f,
1313 int (*cmp) (const char *, const char *),
1314 unsigned long (*hash) (const char *))
1315{
1316 if (cmp)
1317 f->symbol_cmp = cmp;
1318 if (hash) {
1319 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1320 int i;
1321
1322 f->symbol_hash = hash;
1323
1324 memcpy(tmptab, f->symtab, sizeof(tmptab));
1325 memset(f->symtab, 0, sizeof(f->symtab));
1326
1327 for (i = 0; i < HASH_BUCKETS; ++i)
1328 for (sym = tmptab[i]; sym; sym = next) {
1329 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1330 next = sym->next;
1331 sym->next = f->symtab[h];
1332 f->symtab[h] = sym;
1333 }
1334 }
1335}
1336
1337#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1338
1339
1340struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1341 unsigned long symidx, int info,
1342 int secidx, ElfW(Addr) value,
1343 unsigned long size)
1344{
1345 struct obj_symbol *sym;
1346 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1347 int n_type = ELFW(ST_TYPE) (info);
1348 int n_binding = ELFW(ST_BIND) (info);
1349
1350 for (sym = f->symtab[hash]; sym; sym = sym->next)
1351 if (f->symbol_cmp(sym->name, name) == 0) {
1352 int o_secidx = sym->secidx;
1353 int o_info = sym->info;
1354 int o_type = ELFW(ST_TYPE) (o_info);
1355 int o_binding = ELFW(ST_BIND) (o_info);
1356
1357 /* A redefinition! Is it legal? */
1358
1359 if (secidx == SHN_UNDEF)
1360 return sym;
1361 else if (o_secidx == SHN_UNDEF)
1362 goto found;
1363 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1364 /* Cope with local and global symbols of the same name
1365 in the same object file, as might have been created
1366 by ld -r. The only reason locals are now seen at this
1367 level at all is so that we can do semi-sensible things
1368 with parameters. */
1369
1370 struct obj_symbol *nsym, **p;
1371
1372 nsym = arch_new_symbol();
1373 nsym->next = sym->next;
1374 nsym->ksymidx = -1;
1375
1376 /* Excise the old (local) symbol from the hash chain. */
1377 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1378 continue;
1379 *p = sym = nsym;
1380 goto found;
1381 } else if (n_binding == STB_LOCAL) {
1382 /* Another symbol of the same name has already been defined.
1383 Just add this to the local table. */
1384 sym = arch_new_symbol();
1385 sym->next = NULL;
1386 sym->ksymidx = -1;
1387 f->local_symtab[symidx] = sym;
1388 goto found;
1389 } else if (n_binding == STB_WEAK)
1390 return sym;
1391 else if (o_binding == STB_WEAK)
1392 goto found;
1393 /* Don't unify COMMON symbols with object types the programmer
1394 doesn't expect. */
1395 else if (secidx == SHN_COMMON
1396 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1397 return sym;
1398 else if (o_secidx == SHN_COMMON
1399 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1400 goto found;
1401 else {
1402 /* Don't report an error if the symbol is coming from
1403 the kernel or some external module. */
1404 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001405 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001406 return sym;
1407 }
1408 }
1409
1410 /* Completely new symbol. */
1411 sym = arch_new_symbol();
1412 sym->next = f->symtab[hash];
1413 f->symtab[hash] = sym;
1414 sym->ksymidx = -1;
1415
1416 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1417 f->local_symtab[symidx] = sym;
1418
1419 found:
1420 sym->name = name;
1421 sym->value = value;
1422 sym->size = size;
1423 sym->secidx = secidx;
1424 sym->info = info;
1425
1426 return sym;
1427}
1428
1429struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1430{
1431 struct obj_symbol *sym;
1432 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1433
1434 for (sym = f->symtab[hash]; sym; sym = sym->next)
1435 if (f->symbol_cmp(sym->name, name) == 0)
1436 return sym;
1437
1438 return NULL;
1439}
1440
1441ElfW(Addr)
1442 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1443{
1444 if (sym) {
1445 if (sym->secidx >= SHN_LORESERVE)
1446 return sym->value;
1447
1448 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1449 } else {
1450 /* As a special case, a NULL sym has value zero. */
1451 return 0;
1452 }
1453}
1454
1455struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1456{
1457 int i, n = f->header.e_shnum;
1458
1459 for (i = 0; i < n; ++i)
1460 if (strcmp(f->sections[i]->name, name) == 0)
1461 return f->sections[i];
1462
1463 return NULL;
1464}
1465
1466static int obj_load_order_prio(struct obj_section *a)
1467{
1468 unsigned long af, ac;
1469
1470 af = a->header.sh_flags;
1471
1472 ac = 0;
1473 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1474 strcmp(a->name + 5, ".init"))
1475 ac |= 32;
1476 if (af & SHF_ALLOC)
1477 ac |= 16;
1478 if (!(af & SHF_WRITE))
1479 ac |= 8;
1480 if (af & SHF_EXECINSTR)
1481 ac |= 4;
1482 if (a->header.sh_type != SHT_NOBITS)
1483 ac |= 2;
1484
1485 return ac;
1486}
1487
1488void
1489obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1490{
1491 struct obj_section **p;
1492 int prio = obj_load_order_prio(sec);
1493 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1494 if (obj_load_order_prio(*p) < prio)
1495 break;
1496 sec->load_next = *p;
1497 *p = sec;
1498}
1499
1500struct obj_section *obj_create_alloced_section(struct obj_file *f,
1501 const char *name,
1502 unsigned long align,
1503 unsigned long size)
1504{
1505 int newidx = f->header.e_shnum++;
1506 struct obj_section *sec;
1507
1508 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1509 f->sections[newidx] = sec = arch_new_section();
1510
1511 memset(sec, 0, sizeof(*sec));
1512 sec->header.sh_type = SHT_PROGBITS;
1513 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1514 sec->header.sh_size = size;
1515 sec->header.sh_addralign = align;
1516 sec->name = name;
1517 sec->idx = newidx;
1518 if (size)
1519 sec->contents = xmalloc(size);
1520
1521 obj_insert_section_load_order(f, sec);
1522
1523 return sec;
1524}
1525
1526struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1527 const char *name,
1528 unsigned long align,
1529 unsigned long size)
1530{
1531 int newidx = f->header.e_shnum++;
1532 struct obj_section *sec;
1533
1534 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1535 f->sections[newidx] = sec = arch_new_section();
1536
1537 memset(sec, 0, sizeof(*sec));
1538 sec->header.sh_type = SHT_PROGBITS;
1539 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1540 sec->header.sh_size = size;
1541 sec->header.sh_addralign = align;
1542 sec->name = name;
1543 sec->idx = newidx;
1544 if (size)
1545 sec->contents = xmalloc(size);
1546
1547 sec->load_next = f->load_order;
1548 f->load_order = sec;
1549 if (f->load_order_search_start == &f->load_order)
1550 f->load_order_search_start = &sec->load_next;
1551
1552 return sec;
1553}
1554
1555void *obj_extend_section(struct obj_section *sec, unsigned long more)
1556{
1557 unsigned long oldsize = sec->header.sh_size;
1558 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1559 return sec->contents + oldsize;
1560}
1561
1562
1563
1564/* Conditionally add the symbols from the given symbol set to the
1565 new module. */
1566
1567static int
1568add_symbols_from(
1569 struct obj_file *f,
1570 int idx, struct new_module_symbol *syms, size_t nsyms)
1571{
1572 struct new_module_symbol *s;
1573 size_t i;
1574 int used = 0;
1575
1576 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1577
1578 /* Only add symbols that are already marked external. If we
1579 override locals we may cause problems for argument initialization.
1580 We will also create a false dependency on the module. */
1581 struct obj_symbol *sym;
1582
1583 sym = obj_find_symbol(f, (char *) s->name);
1584 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1585 sym = obj_add_symbol(f, (char *) s->name, -1,
1586 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1587 idx, s->value, 0);
1588 /* Did our symbol just get installed? If so, mark the
1589 module as "used". */
1590 if (sym->secidx == idx)
1591 used = 1;
1592 }
1593 }
1594
1595 return used;
1596}
1597
1598static void add_kernel_symbols(struct obj_file *f)
1599{
1600 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001601 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001602
1603 /* Add module symbols first. */
1604
1605 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1606 if (m->nsyms
1607 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1608 m->nsyms)) m->used = 1, ++nused;
1609
1610 n_ext_modules_used = nused;
1611
1612 /* And finally the symbols from the kernel proper. */
1613
1614 if (nksyms)
1615 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1616}
1617
1618static char *get_modinfo_value(struct obj_file *f, const char *key)
1619{
1620 struct obj_section *sec;
1621 char *p, *v, *n, *ep;
1622 size_t klen = strlen(key);
1623
1624 sec = obj_find_section(f, ".modinfo");
1625 if (sec == NULL)
1626 return NULL;
1627 p = sec->contents;
1628 ep = p + sec->header.sh_size;
1629 while (p < ep) {
1630 v = strchr(p, '=');
1631 n = strchr(p, '\0');
1632 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001633 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001634 return v + 1;
1635 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001636 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001637 return n;
1638 }
1639 p = n + 1;
1640 }
1641
1642 return NULL;
1643}
1644
1645
1646/*======================================================================*/
1647/* Functions relating to module loading in pre 2.1 kernels. */
1648
1649static int
1650old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1651{
1652 while (argc > 0) {
1653 char *p, *q;
1654 struct obj_symbol *sym;
1655 int *loc;
1656
1657 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001658 if ((q = strchr(p, '=')) == NULL) {
1659 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001660 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001661 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001662 *q++ = '\0';
1663
1664 sym = obj_find_symbol(f, p);
1665
1666 /* Also check that the parameter was not resolved from the kernel. */
1667 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001668 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001669 return 0;
1670 }
1671
1672 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1673
1674 /* Do C quoting if we begin with a ". */
1675 if (*q == '"') {
1676 char *r, *str;
1677
1678 str = alloca(strlen(q));
1679 for (r = str, q++; *q != '"'; ++q, ++r) {
1680 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001681 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001682 return 0;
1683 } else if (*q == '\\')
1684 switch (*++q) {
1685 case 'a':
1686 *r = '\a';
1687 break;
1688 case 'b':
1689 *r = '\b';
1690 break;
1691 case 'e':
1692 *r = '\033';
1693 break;
1694 case 'f':
1695 *r = '\f';
1696 break;
1697 case 'n':
1698 *r = '\n';
1699 break;
1700 case 'r':
1701 *r = '\r';
1702 break;
1703 case 't':
1704 *r = '\t';
1705 break;
1706
1707 case '0':
1708 case '1':
1709 case '2':
1710 case '3':
1711 case '4':
1712 case '5':
1713 case '6':
1714 case '7':
1715 {
1716 int c = *q - '0';
1717 if (q[1] >= '0' && q[1] <= '7') {
1718 c = (c * 8) + *++q - '0';
1719 if (q[1] >= '0' && q[1] <= '7')
1720 c = (c * 8) + *++q - '0';
1721 }
1722 *r = c;
1723 }
1724 break;
1725
1726 default:
1727 *r = *q;
1728 break;
1729 } else
1730 *r = *q;
1731 }
1732 *r = '\0';
1733 obj_string_patch(f, sym->secidx, sym->value, str);
1734 } else if (*q >= '0' && *q <= '9') {
1735 do
1736 *loc++ = strtoul(q, &q, 0);
1737 while (*q++ == ',');
1738 } else {
1739 char *contents = f->sections[sym->secidx]->contents;
1740 char *loc = contents + sym->value;
1741 char *r; /* To search for commas */
1742
1743 /* Break the string with comas */
1744 while ((r = strchr(q, ',')) != (char *) NULL) {
1745 *r++ = '\0';
1746 obj_string_patch(f, sym->secidx, loc - contents, q);
1747 loc += sizeof(char *);
1748 q = r;
1749 }
1750
1751 /* last part */
1752 obj_string_patch(f, sym->secidx, loc - contents, q);
1753 }
1754
1755 argc--, argv++;
1756 }
1757
1758 return 1;
1759}
1760
1761#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1762static int old_is_module_checksummed(struct obj_file *f)
1763{
1764 return obj_find_symbol(f, "Using_Versions") != NULL;
1765}
1766/* Get the module's kernel version in the canonical integer form. */
1767
1768static int
1769old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1770{
1771 struct obj_symbol *sym;
1772 char *p, *q;
1773 int a, b, c;
1774
1775 sym = obj_find_symbol(f, "kernel_version");
1776 if (sym == NULL)
1777 return -1;
1778
1779 p = f->sections[sym->secidx]->contents + sym->value;
1780 strncpy(str, p, STRVERSIONLEN);
1781
1782 a = strtoul(p, &p, 10);
1783 if (*p != '.')
1784 return -1;
1785 b = strtoul(p + 1, &p, 10);
1786 if (*p != '.')
1787 return -1;
1788 c = strtoul(p + 1, &q, 10);
1789 if (p + 1 == q)
1790 return -1;
1791
1792 return a << 16 | b << 8 | c;
1793}
1794
1795#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1796
Eric Andersenf5d5e772001-01-24 23:34:48 +00001797#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001798
1799/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1800
Eric Andersen8c185f92000-09-22 00:38:07 +00001801static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001802{
1803 struct old_kernel_sym *ks, *k;
1804 struct new_module_symbol *s;
1805 struct external_module *mod;
1806 int nks, nms, nmod, i;
1807
1808 nks = get_kernel_syms(NULL);
1809 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001810 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001811 return 0;
1812 }
1813
1814 ks = k = xmalloc(nks * sizeof(*ks));
1815
1816 if (get_kernel_syms(ks) != nks) {
1817 perror("inconsistency with get_kernel_syms -- is someone else "
1818 "playing with modules?");
1819 free(ks);
1820 return 0;
1821 }
1822
1823 /* Collect the module information. */
1824
1825 mod = NULL;
1826 nmod = -1;
1827
1828 while (k->name[0] == '#' && k->name[1]) {
1829 struct old_kernel_sym *k2;
1830 struct new_module_symbol *s;
1831
1832 /* Find out how many symbols this module has. */
1833 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1834 continue;
1835 nms = k2 - k - 1;
1836
1837 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1838 mod[nmod].name = k->name + 1;
1839 mod[nmod].addr = k->value;
1840 mod[nmod].used = 0;
1841 mod[nmod].nsyms = nms;
1842 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1843
1844 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1845 s->name = (unsigned long) k->name;
1846 s->value = k->value;
1847 }
1848
1849 k = k2;
1850 }
1851
1852 ext_modules = mod;
1853 n_ext_modules = nmod + 1;
1854
1855 /* Now collect the symbols for the kernel proper. */
1856
1857 if (k->name[0] == '#')
1858 ++k;
1859
1860 nksyms = nms = nks - (k - ks);
1861 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1862
1863 for (i = 0; i < nms; ++i, ++s, ++k) {
1864 s->name = (unsigned long) k->name;
1865 s->value = k->value;
1866 }
1867
1868 return 1;
1869}
1870
1871/* Return the kernel symbol checksum version, or zero if not used. */
1872
1873static int old_is_kernel_checksummed(void)
1874{
1875 /* Using_Versions is the first symbol. */
1876 if (nksyms > 0
1877 && strcmp((char *) ksyms[0].name,
1878 "Using_Versions") == 0) return ksyms[0].value;
1879 else
1880 return 0;
1881}
1882
1883
1884static int old_create_mod_use_count(struct obj_file *f)
1885{
1886 struct obj_section *sec;
1887
1888 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1889 sizeof(long));
1890
1891 obj_add_symbol(f, "mod_use_count_", -1,
1892 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1893 sizeof(long));
1894
1895 return 1;
1896}
1897
1898static int
1899old_init_module(const char *m_name, struct obj_file *f,
1900 unsigned long m_size)
1901{
1902 char *image;
1903 struct old_mod_routines routines;
1904 struct old_symbol_table *symtab;
1905 int ret;
1906
1907 /* Create the symbol table */
1908 {
1909 int nsyms = 0, strsize = 0, total;
1910
1911 /* Size things first... */
1912 if (flag_export) {
1913 int i;
1914 for (i = 0; i < HASH_BUCKETS; ++i) {
1915 struct obj_symbol *sym;
1916 for (sym = f->symtab[i]; sym; sym = sym->next)
1917 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1918 && sym->secidx <= SHN_HIRESERVE)
1919 {
1920 sym->ksymidx = nsyms++;
1921 strsize += strlen(sym->name) + 1;
1922 }
1923 }
1924 }
1925
1926 total = (sizeof(struct old_symbol_table)
1927 + nsyms * sizeof(struct old_module_symbol)
1928 + n_ext_modules_used * sizeof(struct old_module_ref)
1929 + strsize);
1930 symtab = xmalloc(total);
1931 symtab->size = total;
1932 symtab->n_symbols = nsyms;
1933 symtab->n_refs = n_ext_modules_used;
1934
1935 if (flag_export && nsyms) {
1936 struct old_module_symbol *ksym;
1937 char *str;
1938 int i;
1939
1940 ksym = symtab->symbol;
1941 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1942 + n_ext_modules_used * sizeof(struct old_module_ref));
1943
1944 for (i = 0; i < HASH_BUCKETS; ++i) {
1945 struct obj_symbol *sym;
1946 for (sym = f->symtab[i]; sym; sym = sym->next)
1947 if (sym->ksymidx >= 0) {
1948 ksym->addr = obj_symbol_final_value(f, sym);
1949 ksym->name =
1950 (unsigned long) str - (unsigned long) symtab;
1951
Matt Kraai70a78552001-01-04 02:00:17 +00001952 strcpy(str, sym->name);
1953 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001954 ksym++;
1955 }
1956 }
1957 }
1958
1959 if (n_ext_modules_used) {
1960 struct old_module_ref *ref;
1961 int i;
1962
1963 ref = (struct old_module_ref *)
1964 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1965
1966 for (i = 0; i < n_ext_modules; ++i)
1967 if (ext_modules[i].used)
1968 ref++->module = ext_modules[i].addr;
1969 }
1970 }
1971
1972 /* Fill in routines. */
1973
1974 routines.init =
1975 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1976 routines.cleanup =
1977 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1978
1979 /* Whew! All of the initialization is complete. Collect the final
1980 module image and give it to the kernel. */
1981
1982 image = xmalloc(m_size);
1983 obj_create_image(f, image);
1984
1985 /* image holds the complete relocated module, accounting correctly for
1986 mod_use_count. However the old module kernel support assume that
1987 it is receiving something which does not contain mod_use_count. */
1988 ret = old_sys_init_module(m_name, image + sizeof(long),
1989 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1990 : 0), &routines, symtab);
1991 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001992 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001993
1994 free(image);
1995 free(symtab);
1996
1997 return ret == 0;
1998}
1999
2000#else
2001
2002#define old_create_mod_use_count(x) TRUE
2003#define old_init_module(x, y, z) TRUE
2004
Eric Andersenf5d5e772001-01-24 23:34:48 +00002005#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002006
2007
2008
2009/*======================================================================*/
2010/* Functions relating to module loading after 2.1.18. */
2011
2012static int
2013new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2014{
2015 while (argc > 0) {
2016 char *p, *q, *key;
2017 struct obj_symbol *sym;
2018 char *contents, *loc;
2019 int min, max, n;
2020
2021 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002022 if ((q = strchr(p, '=')) == NULL) {
2023 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002024 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002025 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002026
2027 key = alloca(q - p + 6);
2028 memcpy(key, "parm_", 5);
2029 memcpy(key + 5, p, q - p);
2030 key[q - p + 5] = 0;
2031
2032 p = get_modinfo_value(f, key);
2033 key += 5;
2034 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002035 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002036 return 0;
2037 }
2038
2039 sym = obj_find_symbol(f, key);
2040
2041 /* Also check that the parameter was not resolved from the kernel. */
2042 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002043 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002044 return 0;
2045 }
2046
2047 if (isdigit(*p)) {
2048 min = strtoul(p, &p, 10);
2049 if (*p == '-')
2050 max = strtoul(p + 1, &p, 10);
2051 else
2052 max = min;
2053 } else
2054 min = max = 1;
2055
2056 contents = f->sections[sym->secidx]->contents;
2057 loc = contents + sym->value;
2058 n = (*++q != '\0');
2059
2060 while (1) {
2061 if ((*p == 's') || (*p == 'c')) {
2062 char *str;
2063
2064 /* Do C quoting if we begin with a ", else slurp the lot. */
2065 if (*q == '"') {
2066 char *r;
2067
2068 str = alloca(strlen(q));
2069 for (r = str, q++; *q != '"'; ++q, ++r) {
2070 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002071 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002072 key);
2073 return 0;
2074 } else if (*q == '\\')
2075 switch (*++q) {
2076 case 'a':
2077 *r = '\a';
2078 break;
2079 case 'b':
2080 *r = '\b';
2081 break;
2082 case 'e':
2083 *r = '\033';
2084 break;
2085 case 'f':
2086 *r = '\f';
2087 break;
2088 case 'n':
2089 *r = '\n';
2090 break;
2091 case 'r':
2092 *r = '\r';
2093 break;
2094 case 't':
2095 *r = '\t';
2096 break;
2097
2098 case '0':
2099 case '1':
2100 case '2':
2101 case '3':
2102 case '4':
2103 case '5':
2104 case '6':
2105 case '7':
2106 {
2107 int c = *q - '0';
2108 if (q[1] >= '0' && q[1] <= '7') {
2109 c = (c * 8) + *++q - '0';
2110 if (q[1] >= '0' && q[1] <= '7')
2111 c = (c * 8) + *++q - '0';
2112 }
2113 *r = c;
2114 }
2115 break;
2116
2117 default:
2118 *r = *q;
2119 break;
2120 } else
2121 *r = *q;
2122 }
2123 *r = '\0';
2124 ++q;
2125 } else {
2126 char *r;
2127
2128 /* In this case, the string is not quoted. We will break
2129 it using the coma (like for ints). If the user wants to
2130 include comas in a string, he just has to quote it */
2131
2132 /* Search the next coma */
2133 r = strchr(q, ',');
2134
2135 /* Found ? */
2136 if (r != (char *) NULL) {
2137 /* Recopy the current field */
2138 str = alloca(r - q + 1);
2139 memcpy(str, q, r - q);
2140
2141 /* I don't know if it is usefull, as the previous case
2142 doesn't null terminate the string ??? */
2143 str[r - q] = '\0';
2144
2145 /* Keep next fields */
2146 q = r;
2147 } else {
2148 /* last string */
2149 str = q;
2150 q = "";
2151 }
2152 }
2153
2154 if (*p == 's') {
2155 /* Normal string */
2156 obj_string_patch(f, sym->secidx, loc - contents, str);
2157 loc += tgt_sizeof_char_p;
2158 } else {
2159 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002160 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002161
2162 /* Get the size of each member */
2163 /* Probably we should do that outside the loop ? */
2164 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002165 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002166 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002167 return 0;
2168 }
2169 charssize = strtoul(p + 1, (char **) NULL, 10);
2170
2171 /* Check length */
2172 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002173 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002174 charssize - 1);
2175 return 0;
2176 }
2177
2178 /* Copy to location */
2179 strcpy((char *) loc, str);
2180 loc += charssize;
2181 }
2182 } else {
2183 long v = strtoul(q, &q, 0);
2184 switch (*p) {
2185 case 'b':
2186 *loc++ = v;
2187 break;
2188 case 'h':
2189 *(short *) loc = v;
2190 loc += tgt_sizeof_short;
2191 break;
2192 case 'i':
2193 *(int *) loc = v;
2194 loc += tgt_sizeof_int;
2195 break;
2196 case 'l':
2197 *(long *) loc = v;
2198 loc += tgt_sizeof_long;
2199 break;
2200
2201 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002202 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002203 return 0;
2204 }
2205 }
2206
2207 retry_end_of_value:
2208 switch (*q) {
2209 case '\0':
2210 goto end_of_arg;
2211
2212 case ' ':
2213 case '\t':
2214 case '\n':
2215 case '\r':
2216 ++q;
2217 goto retry_end_of_value;
2218
2219 case ',':
2220 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002221 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002222 return 0;
2223 }
2224 ++q;
2225 break;
2226
2227 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002228 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002229 return 0;
2230 }
2231 }
2232
2233 end_of_arg:
2234 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002235 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002236 return 0;
2237 }
2238
2239 argc--, argv++;
2240 }
2241
2242 return 1;
2243}
2244
2245#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2246static int new_is_module_checksummed(struct obj_file *f)
2247{
2248 const char *p = get_modinfo_value(f, "using_checksums");
2249 if (p)
2250 return atoi(p);
2251 else
2252 return 0;
2253}
2254
2255/* Get the module's kernel version in the canonical integer form. */
2256
2257static int
2258new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2259{
2260 char *p, *q;
2261 int a, b, c;
2262
2263 p = get_modinfo_value(f, "kernel_version");
2264 if (p == NULL)
2265 return -1;
2266 strncpy(str, p, STRVERSIONLEN);
2267
2268 a = strtoul(p, &p, 10);
2269 if (*p != '.')
2270 return -1;
2271 b = strtoul(p + 1, &p, 10);
2272 if (*p != '.')
2273 return -1;
2274 c = strtoul(p + 1, &q, 10);
2275 if (p + 1 == q)
2276 return -1;
2277
2278 return a << 16 | b << 8 | c;
2279}
2280
2281#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2282
2283
Eric Andersenf5d5e772001-01-24 23:34:48 +00002284#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002285
2286/* Fetch the loaded modules, and all currently exported symbols. */
2287
2288static int new_get_kernel_symbols(void)
2289{
2290 char *module_names, *mn;
2291 struct external_module *modules, *m;
2292 struct new_module_symbol *syms, *s;
2293 size_t ret, bufsize, nmod, nsyms, i, j;
2294
2295 /* Collect the loaded modules. */
2296
2297 module_names = xmalloc(bufsize = 256);
2298 retry_modules_load:
2299 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2300 if (errno == ENOSPC) {
2301 module_names = xrealloc(module_names, bufsize = ret);
2302 goto retry_modules_load;
2303 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002304 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002305 return 0;
2306 }
2307
2308 n_ext_modules = nmod = ret;
2309 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2310 memset(modules, 0, nmod * sizeof(*modules));
2311
2312 /* Collect the modules' symbols. */
2313
2314 for (i = 0, mn = module_names, m = modules;
2315 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2316 struct new_module_info info;
2317
2318 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2319 if (errno == ENOENT) {
2320 /* The module was removed out from underneath us. */
2321 continue;
2322 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002323 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002324 return 0;
2325 }
2326
2327 syms = xmalloc(bufsize = 1024);
2328 retry_mod_sym_load:
2329 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2330 switch (errno) {
2331 case ENOSPC:
2332 syms = xrealloc(syms, bufsize = ret);
2333 goto retry_mod_sym_load;
2334 case ENOENT:
2335 /* The module was removed out from underneath us. */
2336 continue;
2337 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002338 perror_msg("query_module: QM_SYMBOLS: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002339 return 0;
2340 }
2341 }
2342 nsyms = ret;
2343
2344 m->name = mn;
2345 m->addr = info.addr;
2346 m->nsyms = nsyms;
2347 m->syms = syms;
2348
2349 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2350 s->name += (unsigned long) syms;
2351 }
2352 }
2353
2354 /* Collect the kernel's symbols. */
2355
2356 syms = xmalloc(bufsize = 16 * 1024);
2357 retry_kern_sym_load:
2358 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2359 if (errno == ENOSPC) {
2360 syms = xrealloc(syms, bufsize = ret);
2361 goto retry_kern_sym_load;
2362 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002363 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002364 return 0;
2365 }
2366 nksyms = nsyms = ret;
2367 ksyms = syms;
2368
2369 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2370 s->name += (unsigned long) syms;
2371 }
2372 return 1;
2373}
2374
2375
2376/* Return the kernel symbol checksum version, or zero if not used. */
2377
2378static int new_is_kernel_checksummed(void)
2379{
2380 struct new_module_symbol *s;
2381 size_t i;
2382
2383 /* Using_Versions is not the first symbol, but it should be in there. */
2384
2385 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2386 if (strcmp((char *) s->name, "Using_Versions") == 0)
2387 return s->value;
2388
2389 return 0;
2390}
2391
2392
2393static int new_create_this_module(struct obj_file *f, const char *m_name)
2394{
2395 struct obj_section *sec;
2396
2397 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2398 sizeof(struct new_module));
2399 memset(sec->contents, 0, sizeof(struct new_module));
2400
2401 obj_add_symbol(f, "__this_module", -1,
2402 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2403 sizeof(struct new_module));
2404
2405 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2406 m_name);
2407
2408 return 1;
2409}
2410
2411
2412static int new_create_module_ksymtab(struct obj_file *f)
2413{
2414 struct obj_section *sec;
2415 int i;
2416
2417 /* We must always add the module references. */
2418
2419 if (n_ext_modules_used) {
2420 struct new_module_ref *dep;
2421 struct obj_symbol *tm;
2422
2423 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2424 (sizeof(struct new_module_ref)
2425 * n_ext_modules_used));
2426 if (!sec)
2427 return 0;
2428
2429 tm = obj_find_symbol(f, "__this_module");
2430 dep = (struct new_module_ref *) sec->contents;
2431 for (i = 0; i < n_ext_modules; ++i)
2432 if (ext_modules[i].used) {
2433 dep->dep = ext_modules[i].addr;
2434 obj_symbol_patch(f, sec->idx,
2435 (char *) &dep->ref - sec->contents, tm);
2436 dep->next_ref = 0;
2437 ++dep;
2438 }
2439 }
2440
2441 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2442 size_t nsyms;
2443 int *loaded;
2444
2445 sec =
2446 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2447 0);
2448
2449 /* We don't want to export symbols residing in sections that
2450 aren't loaded. There are a number of these created so that
2451 we make sure certain module options don't appear twice. */
2452
2453 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2454 while (--i >= 0)
2455 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2456
2457 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2458 struct obj_symbol *sym;
2459 for (sym = f->symtab[i]; sym; sym = sym->next)
2460 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2461 && sym->secidx <= SHN_HIRESERVE
2462 && (sym->secidx >= SHN_LORESERVE
2463 || loaded[sym->secidx])) {
2464 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2465
2466 obj_symbol_patch(f, sec->idx, ofs, sym);
2467 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2468 sym->name);
2469
2470 nsyms++;
2471 }
2472 }
2473
2474 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2475 }
2476
2477 return 1;
2478}
2479
2480
2481static int
2482new_init_module(const char *m_name, struct obj_file *f,
2483 unsigned long m_size)
2484{
2485 struct new_module *module;
2486 struct obj_section *sec;
2487 void *image;
2488 int ret;
2489 tgt_long m_addr;
2490
2491 sec = obj_find_section(f, ".this");
2492 module = (struct new_module *) sec->contents;
2493 m_addr = sec->header.sh_addr;
2494
2495 module->size_of_struct = sizeof(*module);
2496 module->size = m_size;
2497 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2498
2499 sec = obj_find_section(f, "__ksymtab");
2500 if (sec && sec->header.sh_size) {
2501 module->syms = sec->header.sh_addr;
2502 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2503 }
2504
2505 if (n_ext_modules_used) {
2506 sec = obj_find_section(f, ".kmodtab");
2507 module->deps = sec->header.sh_addr;
2508 module->ndeps = n_ext_modules_used;
2509 }
2510
2511 module->init =
2512 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2513 module->cleanup =
2514 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2515
2516 sec = obj_find_section(f, "__ex_table");
2517 if (sec) {
2518 module->ex_table_start = sec->header.sh_addr;
2519 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2520 }
2521
2522 sec = obj_find_section(f, ".text.init");
2523 if (sec) {
2524 module->runsize = sec->header.sh_addr - m_addr;
2525 }
2526 sec = obj_find_section(f, ".data.init");
2527 if (sec) {
2528 if (!module->runsize ||
2529 module->runsize > sec->header.sh_addr - m_addr)
2530 module->runsize = sec->header.sh_addr - m_addr;
2531 }
2532
2533 if (!arch_init_module(f, module))
2534 return 0;
2535
2536 /* Whew! All of the initialization is complete. Collect the final
2537 module image and give it to the kernel. */
2538
2539 image = xmalloc(m_size);
2540 obj_create_image(f, image);
2541
2542 ret = new_sys_init_module(m_name, (struct new_module *) image);
2543 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002544 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002545
2546 free(image);
2547
2548 return ret == 0;
2549}
2550
2551#else
2552
2553#define new_init_module(x, y, z) TRUE
2554#define new_create_this_module(x, y) 0
2555#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002556#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002557
Eric Andersenf5d5e772001-01-24 23:34:48 +00002558#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002559
2560
2561/*======================================================================*/
2562
2563int
2564obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2565 const char *string)
2566{
2567 struct obj_string_patch *p;
2568 struct obj_section *strsec;
2569 size_t len = strlen(string) + 1;
2570 char *loc;
2571
2572 p = xmalloc(sizeof(*p));
2573 p->next = f->string_patches;
2574 p->reloc_secidx = secidx;
2575 p->reloc_offset = offset;
2576 f->string_patches = p;
2577
2578 strsec = obj_find_section(f, ".kstrtab");
2579 if (strsec == NULL) {
2580 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2581 p->string_offset = 0;
2582 loc = strsec->contents;
2583 } else {
2584 p->string_offset = strsec->header.sh_size;
2585 loc = obj_extend_section(strsec, len);
2586 }
2587 memcpy(loc, string, len);
2588
2589 return 1;
2590}
2591
2592int
2593obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2594 struct obj_symbol *sym)
2595{
2596 struct obj_symbol_patch *p;
2597
2598 p = xmalloc(sizeof(*p));
2599 p->next = f->symbol_patches;
2600 p->reloc_secidx = secidx;
2601 p->reloc_offset = offset;
2602 p->sym = sym;
2603 f->symbol_patches = p;
2604
2605 return 1;
2606}
2607
2608int obj_check_undefineds(struct obj_file *f)
2609{
2610 unsigned long i;
2611 int ret = 1;
2612
2613 for (i = 0; i < HASH_BUCKETS; ++i) {
2614 struct obj_symbol *sym;
2615 for (sym = f->symtab[i]; sym; sym = sym->next)
2616 if (sym->secidx == SHN_UNDEF) {
2617 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2618 sym->secidx = SHN_ABS;
2619 sym->value = 0;
2620 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002621 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002622 ret = 0;
2623 }
2624 }
2625 }
2626
2627 return ret;
2628}
2629
2630void obj_allocate_commons(struct obj_file *f)
2631{
2632 struct common_entry {
2633 struct common_entry *next;
2634 struct obj_symbol *sym;
2635 } *common_head = NULL;
2636
2637 unsigned long i;
2638
2639 for (i = 0; i < HASH_BUCKETS; ++i) {
2640 struct obj_symbol *sym;
2641 for (sym = f->symtab[i]; sym; sym = sym->next)
2642 if (sym->secidx == SHN_COMMON) {
2643 /* Collect all COMMON symbols and sort them by size so as to
2644 minimize space wasted by alignment requirements. */
2645 {
2646 struct common_entry **p, *n;
2647 for (p = &common_head; *p; p = &(*p)->next)
2648 if (sym->size <= (*p)->sym->size)
2649 break;
2650
2651 n = alloca(sizeof(*n));
2652 n->next = *p;
2653 n->sym = sym;
2654 *p = n;
2655 }
2656 }
2657 }
2658
2659 for (i = 1; i < f->local_symtab_size; ++i) {
2660 struct obj_symbol *sym = f->local_symtab[i];
2661 if (sym && sym->secidx == SHN_COMMON) {
2662 struct common_entry **p, *n;
2663 for (p = &common_head; *p; p = &(*p)->next)
2664 if (sym == (*p)->sym)
2665 break;
2666 else if (sym->size < (*p)->sym->size) {
2667 n = alloca(sizeof(*n));
2668 n->next = *p;
2669 n->sym = sym;
2670 *p = n;
2671 break;
2672 }
2673 }
2674 }
2675
2676 if (common_head) {
2677 /* Find the bss section. */
2678 for (i = 0; i < f->header.e_shnum; ++i)
2679 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2680 break;
2681
2682 /* If for some reason there hadn't been one, create one. */
2683 if (i == f->header.e_shnum) {
2684 struct obj_section *sec;
2685
2686 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2687 f->sections[i] = sec = arch_new_section();
2688 f->header.e_shnum = i + 1;
2689
2690 memset(sec, 0, sizeof(*sec));
2691 sec->header.sh_type = SHT_PROGBITS;
2692 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2693 sec->name = ".bss";
2694 sec->idx = i;
2695 }
2696
2697 /* Allocate the COMMONS. */
2698 {
2699 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2700 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2701 struct common_entry *c;
2702
2703 for (c = common_head; c; c = c->next) {
2704 ElfW(Addr) align = c->sym->value;
2705
2706 if (align > max_align)
2707 max_align = align;
2708 if (bss_size & (align - 1))
2709 bss_size = (bss_size | (align - 1)) + 1;
2710
2711 c->sym->secidx = i;
2712 c->sym->value = bss_size;
2713
2714 bss_size += c->sym->size;
2715 }
2716
2717 f->sections[i]->header.sh_size = bss_size;
2718 f->sections[i]->header.sh_addralign = max_align;
2719 }
2720 }
2721
2722 /* For the sake of patch relocation and parameter initialization,
2723 allocate zeroed data for NOBITS sections now. Note that after
2724 this we cannot assume NOBITS are really empty. */
2725 for (i = 0; i < f->header.e_shnum; ++i) {
2726 struct obj_section *s = f->sections[i];
2727 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002728 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002729 s->contents = memset(xmalloc(s->header.sh_size),
2730 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002731 else
2732 s->contents = NULL;
2733
Eric Andersen9f16d612000-06-12 23:11:16 +00002734 s->header.sh_type = SHT_PROGBITS;
2735 }
2736 }
2737}
2738
2739unsigned long obj_load_size(struct obj_file *f)
2740{
2741 unsigned long dot = 0;
2742 struct obj_section *sec;
2743
2744 /* Finalize the positions of the sections relative to one another. */
2745
2746 for (sec = f->load_order; sec; sec = sec->load_next) {
2747 ElfW(Addr) align;
2748
2749 align = sec->header.sh_addralign;
2750 if (align && (dot & (align - 1)))
2751 dot = (dot | (align - 1)) + 1;
2752
2753 sec->header.sh_addr = dot;
2754 dot += sec->header.sh_size;
2755 }
2756
2757 return dot;
2758}
2759
2760int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2761{
2762 int i, n = f->header.e_shnum;
2763 int ret = 1;
2764
2765 /* Finalize the addresses of the sections. */
2766
2767 f->baseaddr = base;
2768 for (i = 0; i < n; ++i)
2769 f->sections[i]->header.sh_addr += base;
2770
2771 /* And iterate over all of the relocations. */
2772
2773 for (i = 0; i < n; ++i) {
2774 struct obj_section *relsec, *symsec, *targsec, *strsec;
2775 ElfW(RelM) * rel, *relend;
2776 ElfW(Sym) * symtab;
2777 const char *strtab;
2778
2779 relsec = f->sections[i];
2780 if (relsec->header.sh_type != SHT_RELM)
2781 continue;
2782
2783 symsec = f->sections[relsec->header.sh_link];
2784 targsec = f->sections[relsec->header.sh_info];
2785 strsec = f->sections[symsec->header.sh_link];
2786
2787 rel = (ElfW(RelM) *) relsec->contents;
2788 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2789 symtab = (ElfW(Sym) *) symsec->contents;
2790 strtab = (const char *) strsec->contents;
2791
2792 for (; rel < relend; ++rel) {
2793 ElfW(Addr) value = 0;
2794 struct obj_symbol *intsym = NULL;
2795 unsigned long symndx;
2796 ElfW(Sym) * extsym = 0;
2797 const char *errmsg;
2798
2799 /* Attempt to find a value to use for this relocation. */
2800
2801 symndx = ELFW(R_SYM) (rel->r_info);
2802 if (symndx) {
2803 /* Note we've already checked for undefined symbols. */
2804
2805 extsym = &symtab[symndx];
2806 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2807 /* Local symbols we look up in the local table to be sure
2808 we get the one that is really intended. */
2809 intsym = f->local_symtab[symndx];
2810 } else {
2811 /* Others we look up in the hash table. */
2812 const char *name;
2813 if (extsym->st_name)
2814 name = strtab + extsym->st_name;
2815 else
2816 name = f->sections[extsym->st_shndx]->name;
2817 intsym = obj_find_symbol(f, name);
2818 }
2819
2820 value = obj_symbol_final_value(f, intsym);
2821 intsym->referenced = 1;
2822 }
2823#if SHT_RELM == SHT_RELA
2824#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2825 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2826 if (!extsym || !extsym->st_name ||
2827 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2828#endif
2829 value += rel->r_addend;
2830#endif
2831
2832 /* Do it! */
2833 switch (arch_apply_relocation
2834 (f, targsec, symsec, intsym, rel, value)) {
2835 case obj_reloc_ok:
2836 break;
2837
2838 case obj_reloc_overflow:
2839 errmsg = "Relocation overflow";
2840 goto bad_reloc;
2841 case obj_reloc_dangerous:
2842 errmsg = "Dangerous relocation";
2843 goto bad_reloc;
2844 case obj_reloc_unhandled:
2845 errmsg = "Unhandled relocation";
2846 bad_reloc:
2847 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002848 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002849 (long) ELFW(R_TYPE) (rel->r_info),
2850 strtab + extsym->st_name);
2851 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002852 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002853 (long) ELFW(R_TYPE) (rel->r_info));
2854 }
2855 ret = 0;
2856 break;
2857 }
2858 }
2859 }
2860
2861 /* Finally, take care of the patches. */
2862
2863 if (f->string_patches) {
2864 struct obj_string_patch *p;
2865 struct obj_section *strsec;
2866 ElfW(Addr) strsec_base;
2867 strsec = obj_find_section(f, ".kstrtab");
2868 strsec_base = strsec->header.sh_addr;
2869
2870 for (p = f->string_patches; p; p = p->next) {
2871 struct obj_section *targsec = f->sections[p->reloc_secidx];
2872 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2873 = strsec_base + p->string_offset;
2874 }
2875 }
2876
2877 if (f->symbol_patches) {
2878 struct obj_symbol_patch *p;
2879
2880 for (p = f->symbol_patches; p; p = p->next) {
2881 struct obj_section *targsec = f->sections[p->reloc_secidx];
2882 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2883 = obj_symbol_final_value(f, p->sym);
2884 }
2885 }
2886
2887 return ret;
2888}
2889
2890int obj_create_image(struct obj_file *f, char *image)
2891{
2892 struct obj_section *sec;
2893 ElfW(Addr) base = f->baseaddr;
2894
2895 for (sec = f->load_order; sec; sec = sec->load_next) {
2896 char *secimg;
2897
Eric Andersen2bf658d2001-02-24 20:01:53 +00002898 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002899 continue;
2900
2901 secimg = image + (sec->header.sh_addr - base);
2902
2903 /* Note that we allocated data for NOBITS sections earlier. */
2904 memcpy(secimg, sec->contents, sec->header.sh_size);
2905 }
2906
2907 return 1;
2908}
2909
2910/*======================================================================*/
2911
2912struct obj_file *obj_load(FILE * fp)
2913{
2914 struct obj_file *f;
2915 ElfW(Shdr) * section_headers;
2916 int shnum, i;
2917 char *shstrtab;
2918
2919 /* Read the file header. */
2920
2921 f = arch_new_file();
2922 memset(f, 0, sizeof(*f));
2923 f->symbol_cmp = strcmp;
2924 f->symbol_hash = obj_elf_hash;
2925 f->load_order_search_start = &f->load_order;
2926
2927 fseek(fp, 0, SEEK_SET);
2928 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002929 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 return NULL;
2931 }
2932
2933 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2934 || f->header.e_ident[EI_MAG1] != ELFMAG1
2935 || f->header.e_ident[EI_MAG2] != ELFMAG2
2936 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002937 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002938 return NULL;
2939 }
2940 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2941 || f->header.e_ident[EI_DATA] != ELFDATAM
2942 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2943 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002944 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002945 return NULL;
2946 }
2947 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002948 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002949 return NULL;
2950 }
2951
2952 /* Read the section headers. */
2953
2954 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002955 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00002956 (unsigned long) f->header.e_shentsize,
2957 (unsigned long) sizeof(ElfW(Shdr)));
2958 return NULL;
2959 }
2960
2961 shnum = f->header.e_shnum;
2962 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2963 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2964
2965 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2966 fseek(fp, f->header.e_shoff, SEEK_SET);
2967 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002968 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002969 return NULL;
2970 }
2971
2972 /* Read the section data. */
2973
2974 for (i = 0; i < shnum; ++i) {
2975 struct obj_section *sec;
2976
2977 f->sections[i] = sec = arch_new_section();
2978 memset(sec, 0, sizeof(*sec));
2979
2980 sec->header = section_headers[i];
2981 sec->idx = i;
2982
Eric Andersen2bf658d2001-02-24 20:01:53 +00002983 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002984 case SHT_NULL:
2985 case SHT_NOTE:
2986 case SHT_NOBITS:
2987 /* ignore */
2988 break;
2989
2990 case SHT_PROGBITS:
2991 case SHT_SYMTAB:
2992 case SHT_STRTAB:
2993 case SHT_RELM:
2994 if (sec->header.sh_size > 0) {
2995 sec->contents = xmalloc(sec->header.sh_size);
2996 fseek(fp, sec->header.sh_offset, SEEK_SET);
2997 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002998 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002999 return NULL;
3000 }
3001 } else {
3002 sec->contents = NULL;
3003 }
3004 break;
3005
3006#if SHT_RELM == SHT_REL
3007 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003008 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003009 return NULL;
3010#else
3011 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003012 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003013 return NULL;
3014#endif
3015
3016 default:
3017 if (sec->header.sh_type >= SHT_LOPROC) {
3018 /* Assume processor specific section types are debug
3019 info and can safely be ignored. If this is ever not
3020 the case (Hello MIPS?), don't put ifdefs here but
3021 create an arch_load_proc_section(). */
3022 break;
3023 }
3024
Matt Kraaidd19c692001-01-31 19:00:21 +00003025 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003026 (long) sec->header.sh_type);
3027 return NULL;
3028 }
3029 }
3030
3031 /* Do what sort of interpretation as needed by each section. */
3032
3033 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3034
3035 for (i = 0; i < shnum; ++i) {
3036 struct obj_section *sec = f->sections[i];
3037 sec->name = shstrtab + sec->header.sh_name;
3038 }
3039
3040 for (i = 0; i < shnum; ++i) {
3041 struct obj_section *sec = f->sections[i];
3042
3043 if (sec->header.sh_flags & SHF_ALLOC)
3044 obj_insert_section_load_order(f, sec);
3045
3046 switch (sec->header.sh_type) {
3047 case SHT_SYMTAB:
3048 {
3049 unsigned long nsym, j;
3050 char *strtab;
3051 ElfW(Sym) * sym;
3052
3053 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003054 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003055 (unsigned long) sec->header.sh_entsize,
3056 (unsigned long) sizeof(ElfW(Sym)));
3057 return NULL;
3058 }
3059
3060 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3061 strtab = f->sections[sec->header.sh_link]->contents;
3062 sym = (ElfW(Sym) *) sec->contents;
3063
3064 /* Allocate space for a table of local symbols. */
3065 j = f->local_symtab_size = sec->header.sh_info;
3066 f->local_symtab = xmalloc(j *=
3067 sizeof(struct obj_symbol *));
3068 memset(f->local_symtab, 0, j);
3069
3070 /* Insert all symbols into the hash table. */
3071 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3072 const char *name;
3073 if (sym->st_name)
3074 name = strtab + sym->st_name;
3075 else
3076 name = f->sections[sym->st_shndx]->name;
3077
3078 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3079 sym->st_value, sym->st_size);
3080 }
3081 }
3082 break;
3083
3084 case SHT_RELM:
3085 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003086 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003087 (unsigned long) sec->header.sh_entsize,
3088 (unsigned long) sizeof(ElfW(RelM)));
3089 return NULL;
3090 }
3091 break;
3092 }
3093 }
3094
3095 return f;
3096}
3097
3098static void hide_special_symbols(struct obj_file *f)
3099{
3100 static const char *const specials[] = {
3101 "cleanup_module",
3102 "init_module",
3103 "kernel_version",
3104 NULL
3105 };
3106
3107 struct obj_symbol *sym;
3108 const char *const *p;
3109
3110 for (p = specials; *p; ++p)
3111 if ((sym = obj_find_symbol(f, *p)) != NULL)
3112 sym->info =
3113 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3114}
3115
3116
3117
3118extern int insmod_main( int argc, char **argv)
3119{
Eric Andersena18aaf12001-01-24 19:07:09 +00003120 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003121 int k_crcs;
3122 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003123 int len;
3124 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003125 unsigned long m_size;
3126 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003127 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003128 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003129 struct stat st;
Eric Andersen9f16d612000-06-12 23:11:16 +00003130 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003131 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 int m_has_modinfo;
3133#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3134 int k_version;
3135 char k_strversion[STRVERSIONLEN];
3136 char m_strversion[STRVERSIONLEN];
3137 int m_version;
3138 int m_crcs;
3139#endif
3140
Erik Andersene49d5ec2000-02-08 19:58:47 +00003141 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003142 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003143 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003144 case 'f': /* force loading */
3145 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003146 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003147 case 'k': /* module loaded by kerneld, auto-cleanable */
3148 flag_autoclean = 1;
3149 break;
3150 case 'v': /* verbose output */
3151 flag_verbose = 1;
3152 break;
3153 case 'x': /* do not export externs */
3154 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003155 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003156 case 'o': /* name the output module */
3157 strncpy(m_name, optarg, BUFSIZ);
3158 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003159 case 'L': /* Stub warning */
3160 /* This is needed for compatibility with modprobe.
3161 * In theory, this does locking, but we don't do
3162 * that. So be careful and plan your life around not
3163 * loading the same module 50 times concurrently. */
3164 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003165 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003166 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003167 }
Erik Andersend387d011999-12-21 02:55:11 +00003168 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003169
3170 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003171 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003172 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003173
Erik Andersene49d5ec2000-02-08 19:58:47 +00003174 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003175 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003176 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003177 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003178 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003179 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003180 len = strlen(tmp);
3181
3182 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3183 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00003184 strncpy(m_fullName, tmp, len);
Eric Andersen114ad9c2001-01-26 01:52:14 +00003185 if (*m_name == '\0') {
3186 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003187 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003188 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003189
3190 /* Get a filedesc for the module */
Eric Andersen02b9f422001-02-15 19:07:43 +00003191 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3192 (fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003193 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00003194 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003195 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003196 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003197 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00003198 || ((fp = fopen(m_filename, "r")) == NULL))
3199 {
Matt Kraaidd19c692001-01-31 19:00:21 +00003200 error_msg("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00003201 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003202 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003203 } else
Matt Kraaidd19c692001-01-31 19:00:21 +00003204 error_msg_and_die("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003205 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00003206 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00003207
3208
Matt Kraaia9819b22000-12-22 01:48:07 +00003209 if ((f = obj_load(fp)) == NULL)
3210 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003211
Eric Andersen9f16d612000-06-12 23:11:16 +00003212 if (get_modinfo_value(f, "kernel_version") == NULL)
3213 m_has_modinfo = 0;
3214 else
3215 m_has_modinfo = 1;
3216
3217#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3218 /* Version correspondence? */
3219
3220 k_version = get_kernel_version(k_strversion);
3221 if (m_has_modinfo) {
3222 m_version = new_get_module_version(f, m_strversion);
3223 } else {
3224 m_version = old_get_module_version(f, m_strversion);
3225 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003226 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003227 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003228 goto out;
3229 }
3230 }
3231
3232 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3233 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003234 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003235 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003236 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003237 m_filename, m_strversion, k_strversion);
3238 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003239 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003240 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003241 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003242 m_filename, m_strversion, k_strversion);
3243 goto out;
3244 }
3245 }
3246 k_crcs = 0;
3247#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3248
3249 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3250
3251 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003252#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003253 if (!new_get_kernel_symbols())
3254 goto out;
3255 k_crcs = new_is_kernel_checksummed();
3256#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003257 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003258 goto out;
3259#endif
3260 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003261#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003262 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003263 goto out;
3264 k_crcs = old_is_kernel_checksummed();
3265#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003266 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003267 goto out;
3268#endif
3269 }
3270
3271#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3272 if (m_has_modinfo)
3273 m_crcs = new_is_module_checksummed(f);
3274 else
3275 m_crcs = old_is_module_checksummed(f);
3276
3277 if (m_crcs != k_crcs)
3278 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3279#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3280
Erik Andersene49d5ec2000-02-08 19:58:47 +00003281 /* Let the module know about the kernel symbols. */
3282 add_kernel_symbols(f);
3283
Eric Andersen9f16d612000-06-12 23:11:16 +00003284 /* Allocate common symbols, symbol tables, and string tables. */
3285
3286 if (k_new_syscalls
3287 ? !new_create_this_module(f, m_name)
3288 : !old_create_mod_use_count(f))
3289 {
3290 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003291 }
3292
Eric Andersen9f16d612000-06-12 23:11:16 +00003293 if (!obj_check_undefineds(f)) {
3294 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003295 }
3296 obj_allocate_commons(f);
3297
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003298 /* done with the module name, on to the optional var=value arguments */
3299 ++optind;
3300
Eric Andersen9f16d612000-06-12 23:11:16 +00003301 if (optind < argc) {
3302 if (m_has_modinfo
3303 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3304 : !old_process_module_arguments(f, argc - optind, argv + optind))
3305 {
3306 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003307 }
3308 }
3309
Eric Andersen9f16d612000-06-12 23:11:16 +00003310 arch_create_got(f);
3311 hide_special_symbols(f);
3312
3313 if (k_new_syscalls)
3314 new_create_module_ksymtab(f);
3315
Erik Andersene49d5ec2000-02-08 19:58:47 +00003316 /* Find current size of the module */
3317 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003318
3319
Erik Andersene49d5ec2000-02-08 19:58:47 +00003320 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003321 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003322 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003323 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003324 goto out;
3325 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003326 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003327 m_size);
3328 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003329 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003330 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003331 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003332 }
Erik Andersend387d011999-12-21 02:55:11 +00003333
Eric Andersen9f16d612000-06-12 23:11:16 +00003334 if (!obj_relocate(f, m_addr)) {
3335 delete_module(m_name);
3336 goto out;
3337 }
Erik Andersend387d011999-12-21 02:55:11 +00003338
Eric Andersen9f16d612000-06-12 23:11:16 +00003339 if (k_new_syscalls
3340 ? !new_init_module(m_name, f, m_size)
3341 : !old_init_module(m_name, f, m_size))
3342 {
3343 delete_module(m_name);
3344 goto out;
3345 }
3346
Matt Kraai3e856ce2000-12-01 02:55:13 +00003347 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003348
3349out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003350 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003351 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003352}