blob: 5391c8804990d07983bd61ed5ffa68c4aec8339a [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
Mark Whitley94fd4802001-03-12 23:08:34 +0000122#ident "$Id: insmod.c,v 1.51 2001/03/12 23:08:34 markw 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
Mark Whitley94fd4802001-03-12 23:08:34 +0000328#ident "$Id: insmod.c,v 1.51 2001/03/12 23:08:34 markw 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;
Eric Andersen9f16d612000-06-12 23:11:16 +00002309
2310 /* Collect the modules' symbols. */
2311
Mark Whitley94fd4802001-03-12 23:08:34 +00002312 if (nmod){
2313 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2314 memset(modules, 0, nmod * sizeof(*modules));
2315 for (i = 0, mn = module_names, m = modules;
2316 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2317 struct new_module_info info;
2318
2319 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2320 if (errno == ENOENT) {
2321 /* The module was removed out from underneath us. */
2322 continue;
2323 }
2324 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002325 return 0;
2326 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002327
2328 syms = xmalloc(bufsize = 1024);
2329 retry_mod_sym_load:
2330 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2331 switch (errno) {
2332 case ENOSPC:
2333 syms = xrealloc(syms, bufsize = ret);
2334 goto retry_mod_sym_load;
2335 case ENOENT:
2336 /* The module was removed out from underneath us. */
2337 continue;
2338 default:
2339 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2340 return 0;
2341 }
2342 }
2343 nsyms = ret;
2344
2345 m->name = mn;
2346 m->addr = info.addr;
2347 m->nsyms = nsyms;
2348 m->syms = syms;
2349
2350 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2351 s->name += (unsigned long) syms;
2352 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002353 }
2354 }
2355
2356 /* Collect the kernel's symbols. */
2357
2358 syms = xmalloc(bufsize = 16 * 1024);
2359 retry_kern_sym_load:
2360 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2361 if (errno == ENOSPC) {
2362 syms = xrealloc(syms, bufsize = ret);
2363 goto retry_kern_sym_load;
2364 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002365 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002366 return 0;
2367 }
2368 nksyms = nsyms = ret;
2369 ksyms = syms;
2370
2371 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2372 s->name += (unsigned long) syms;
2373 }
2374 return 1;
2375}
2376
2377
2378/* Return the kernel symbol checksum version, or zero if not used. */
2379
2380static int new_is_kernel_checksummed(void)
2381{
2382 struct new_module_symbol *s;
2383 size_t i;
2384
2385 /* Using_Versions is not the first symbol, but it should be in there. */
2386
2387 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2388 if (strcmp((char *) s->name, "Using_Versions") == 0)
2389 return s->value;
2390
2391 return 0;
2392}
2393
2394
2395static int new_create_this_module(struct obj_file *f, const char *m_name)
2396{
2397 struct obj_section *sec;
2398
2399 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2400 sizeof(struct new_module));
2401 memset(sec->contents, 0, sizeof(struct new_module));
2402
2403 obj_add_symbol(f, "__this_module", -1,
2404 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2405 sizeof(struct new_module));
2406
2407 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2408 m_name);
2409
2410 return 1;
2411}
2412
2413
2414static int new_create_module_ksymtab(struct obj_file *f)
2415{
2416 struct obj_section *sec;
2417 int i;
2418
2419 /* We must always add the module references. */
2420
2421 if (n_ext_modules_used) {
2422 struct new_module_ref *dep;
2423 struct obj_symbol *tm;
2424
2425 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2426 (sizeof(struct new_module_ref)
2427 * n_ext_modules_used));
2428 if (!sec)
2429 return 0;
2430
2431 tm = obj_find_symbol(f, "__this_module");
2432 dep = (struct new_module_ref *) sec->contents;
2433 for (i = 0; i < n_ext_modules; ++i)
2434 if (ext_modules[i].used) {
2435 dep->dep = ext_modules[i].addr;
2436 obj_symbol_patch(f, sec->idx,
2437 (char *) &dep->ref - sec->contents, tm);
2438 dep->next_ref = 0;
2439 ++dep;
2440 }
2441 }
2442
2443 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2444 size_t nsyms;
2445 int *loaded;
2446
2447 sec =
2448 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2449 0);
2450
2451 /* We don't want to export symbols residing in sections that
2452 aren't loaded. There are a number of these created so that
2453 we make sure certain module options don't appear twice. */
2454
2455 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2456 while (--i >= 0)
2457 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2458
2459 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2460 struct obj_symbol *sym;
2461 for (sym = f->symtab[i]; sym; sym = sym->next)
2462 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2463 && sym->secidx <= SHN_HIRESERVE
2464 && (sym->secidx >= SHN_LORESERVE
2465 || loaded[sym->secidx])) {
2466 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2467
2468 obj_symbol_patch(f, sec->idx, ofs, sym);
2469 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2470 sym->name);
2471
2472 nsyms++;
2473 }
2474 }
2475
2476 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2477 }
2478
2479 return 1;
2480}
2481
2482
2483static int
2484new_init_module(const char *m_name, struct obj_file *f,
2485 unsigned long m_size)
2486{
2487 struct new_module *module;
2488 struct obj_section *sec;
2489 void *image;
2490 int ret;
2491 tgt_long m_addr;
2492
2493 sec = obj_find_section(f, ".this");
2494 module = (struct new_module *) sec->contents;
2495 m_addr = sec->header.sh_addr;
2496
2497 module->size_of_struct = sizeof(*module);
2498 module->size = m_size;
2499 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2500
2501 sec = obj_find_section(f, "__ksymtab");
2502 if (sec && sec->header.sh_size) {
2503 module->syms = sec->header.sh_addr;
2504 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2505 }
2506
2507 if (n_ext_modules_used) {
2508 sec = obj_find_section(f, ".kmodtab");
2509 module->deps = sec->header.sh_addr;
2510 module->ndeps = n_ext_modules_used;
2511 }
2512
2513 module->init =
2514 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2515 module->cleanup =
2516 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2517
2518 sec = obj_find_section(f, "__ex_table");
2519 if (sec) {
2520 module->ex_table_start = sec->header.sh_addr;
2521 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2522 }
2523
2524 sec = obj_find_section(f, ".text.init");
2525 if (sec) {
2526 module->runsize = sec->header.sh_addr - m_addr;
2527 }
2528 sec = obj_find_section(f, ".data.init");
2529 if (sec) {
2530 if (!module->runsize ||
2531 module->runsize > sec->header.sh_addr - m_addr)
2532 module->runsize = sec->header.sh_addr - m_addr;
2533 }
2534
2535 if (!arch_init_module(f, module))
2536 return 0;
2537
2538 /* Whew! All of the initialization is complete. Collect the final
2539 module image and give it to the kernel. */
2540
2541 image = xmalloc(m_size);
2542 obj_create_image(f, image);
2543
2544 ret = new_sys_init_module(m_name, (struct new_module *) image);
2545 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002546 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002547
2548 free(image);
2549
2550 return ret == 0;
2551}
2552
2553#else
2554
2555#define new_init_module(x, y, z) TRUE
2556#define new_create_this_module(x, y) 0
2557#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002558#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002559
Eric Andersenf5d5e772001-01-24 23:34:48 +00002560#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002561
2562
2563/*======================================================================*/
2564
2565int
2566obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2567 const char *string)
2568{
2569 struct obj_string_patch *p;
2570 struct obj_section *strsec;
2571 size_t len = strlen(string) + 1;
2572 char *loc;
2573
2574 p = xmalloc(sizeof(*p));
2575 p->next = f->string_patches;
2576 p->reloc_secidx = secidx;
2577 p->reloc_offset = offset;
2578 f->string_patches = p;
2579
2580 strsec = obj_find_section(f, ".kstrtab");
2581 if (strsec == NULL) {
2582 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2583 p->string_offset = 0;
2584 loc = strsec->contents;
2585 } else {
2586 p->string_offset = strsec->header.sh_size;
2587 loc = obj_extend_section(strsec, len);
2588 }
2589 memcpy(loc, string, len);
2590
2591 return 1;
2592}
2593
2594int
2595obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2596 struct obj_symbol *sym)
2597{
2598 struct obj_symbol_patch *p;
2599
2600 p = xmalloc(sizeof(*p));
2601 p->next = f->symbol_patches;
2602 p->reloc_secidx = secidx;
2603 p->reloc_offset = offset;
2604 p->sym = sym;
2605 f->symbol_patches = p;
2606
2607 return 1;
2608}
2609
2610int obj_check_undefineds(struct obj_file *f)
2611{
2612 unsigned long i;
2613 int ret = 1;
2614
2615 for (i = 0; i < HASH_BUCKETS; ++i) {
2616 struct obj_symbol *sym;
2617 for (sym = f->symtab[i]; sym; sym = sym->next)
2618 if (sym->secidx == SHN_UNDEF) {
2619 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2620 sym->secidx = SHN_ABS;
2621 sym->value = 0;
2622 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002623 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002624 ret = 0;
2625 }
2626 }
2627 }
2628
2629 return ret;
2630}
2631
2632void obj_allocate_commons(struct obj_file *f)
2633{
2634 struct common_entry {
2635 struct common_entry *next;
2636 struct obj_symbol *sym;
2637 } *common_head = NULL;
2638
2639 unsigned long i;
2640
2641 for (i = 0; i < HASH_BUCKETS; ++i) {
2642 struct obj_symbol *sym;
2643 for (sym = f->symtab[i]; sym; sym = sym->next)
2644 if (sym->secidx == SHN_COMMON) {
2645 /* Collect all COMMON symbols and sort them by size so as to
2646 minimize space wasted by alignment requirements. */
2647 {
2648 struct common_entry **p, *n;
2649 for (p = &common_head; *p; p = &(*p)->next)
2650 if (sym->size <= (*p)->sym->size)
2651 break;
2652
2653 n = alloca(sizeof(*n));
2654 n->next = *p;
2655 n->sym = sym;
2656 *p = n;
2657 }
2658 }
2659 }
2660
2661 for (i = 1; i < f->local_symtab_size; ++i) {
2662 struct obj_symbol *sym = f->local_symtab[i];
2663 if (sym && sym->secidx == SHN_COMMON) {
2664 struct common_entry **p, *n;
2665 for (p = &common_head; *p; p = &(*p)->next)
2666 if (sym == (*p)->sym)
2667 break;
2668 else if (sym->size < (*p)->sym->size) {
2669 n = alloca(sizeof(*n));
2670 n->next = *p;
2671 n->sym = sym;
2672 *p = n;
2673 break;
2674 }
2675 }
2676 }
2677
2678 if (common_head) {
2679 /* Find the bss section. */
2680 for (i = 0; i < f->header.e_shnum; ++i)
2681 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2682 break;
2683
2684 /* If for some reason there hadn't been one, create one. */
2685 if (i == f->header.e_shnum) {
2686 struct obj_section *sec;
2687
2688 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2689 f->sections[i] = sec = arch_new_section();
2690 f->header.e_shnum = i + 1;
2691
2692 memset(sec, 0, sizeof(*sec));
2693 sec->header.sh_type = SHT_PROGBITS;
2694 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2695 sec->name = ".bss";
2696 sec->idx = i;
2697 }
2698
2699 /* Allocate the COMMONS. */
2700 {
2701 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2702 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2703 struct common_entry *c;
2704
2705 for (c = common_head; c; c = c->next) {
2706 ElfW(Addr) align = c->sym->value;
2707
2708 if (align > max_align)
2709 max_align = align;
2710 if (bss_size & (align - 1))
2711 bss_size = (bss_size | (align - 1)) + 1;
2712
2713 c->sym->secidx = i;
2714 c->sym->value = bss_size;
2715
2716 bss_size += c->sym->size;
2717 }
2718
2719 f->sections[i]->header.sh_size = bss_size;
2720 f->sections[i]->header.sh_addralign = max_align;
2721 }
2722 }
2723
2724 /* For the sake of patch relocation and parameter initialization,
2725 allocate zeroed data for NOBITS sections now. Note that after
2726 this we cannot assume NOBITS are really empty. */
2727 for (i = 0; i < f->header.e_shnum; ++i) {
2728 struct obj_section *s = f->sections[i];
2729 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002730 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002731 s->contents = memset(xmalloc(s->header.sh_size),
2732 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002733 else
2734 s->contents = NULL;
2735
Eric Andersen9f16d612000-06-12 23:11:16 +00002736 s->header.sh_type = SHT_PROGBITS;
2737 }
2738 }
2739}
2740
2741unsigned long obj_load_size(struct obj_file *f)
2742{
2743 unsigned long dot = 0;
2744 struct obj_section *sec;
2745
2746 /* Finalize the positions of the sections relative to one another. */
2747
2748 for (sec = f->load_order; sec; sec = sec->load_next) {
2749 ElfW(Addr) align;
2750
2751 align = sec->header.sh_addralign;
2752 if (align && (dot & (align - 1)))
2753 dot = (dot | (align - 1)) + 1;
2754
2755 sec->header.sh_addr = dot;
2756 dot += sec->header.sh_size;
2757 }
2758
2759 return dot;
2760}
2761
2762int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2763{
2764 int i, n = f->header.e_shnum;
2765 int ret = 1;
2766
2767 /* Finalize the addresses of the sections. */
2768
2769 f->baseaddr = base;
2770 for (i = 0; i < n; ++i)
2771 f->sections[i]->header.sh_addr += base;
2772
2773 /* And iterate over all of the relocations. */
2774
2775 for (i = 0; i < n; ++i) {
2776 struct obj_section *relsec, *symsec, *targsec, *strsec;
2777 ElfW(RelM) * rel, *relend;
2778 ElfW(Sym) * symtab;
2779 const char *strtab;
2780
2781 relsec = f->sections[i];
2782 if (relsec->header.sh_type != SHT_RELM)
2783 continue;
2784
2785 symsec = f->sections[relsec->header.sh_link];
2786 targsec = f->sections[relsec->header.sh_info];
2787 strsec = f->sections[symsec->header.sh_link];
2788
2789 rel = (ElfW(RelM) *) relsec->contents;
2790 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2791 symtab = (ElfW(Sym) *) symsec->contents;
2792 strtab = (const char *) strsec->contents;
2793
2794 for (; rel < relend; ++rel) {
2795 ElfW(Addr) value = 0;
2796 struct obj_symbol *intsym = NULL;
2797 unsigned long symndx;
2798 ElfW(Sym) * extsym = 0;
2799 const char *errmsg;
2800
2801 /* Attempt to find a value to use for this relocation. */
2802
2803 symndx = ELFW(R_SYM) (rel->r_info);
2804 if (symndx) {
2805 /* Note we've already checked for undefined symbols. */
2806
2807 extsym = &symtab[symndx];
2808 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2809 /* Local symbols we look up in the local table to be sure
2810 we get the one that is really intended. */
2811 intsym = f->local_symtab[symndx];
2812 } else {
2813 /* Others we look up in the hash table. */
2814 const char *name;
2815 if (extsym->st_name)
2816 name = strtab + extsym->st_name;
2817 else
2818 name = f->sections[extsym->st_shndx]->name;
2819 intsym = obj_find_symbol(f, name);
2820 }
2821
2822 value = obj_symbol_final_value(f, intsym);
2823 intsym->referenced = 1;
2824 }
2825#if SHT_RELM == SHT_RELA
2826#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2827 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2828 if (!extsym || !extsym->st_name ||
2829 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2830#endif
2831 value += rel->r_addend;
2832#endif
2833
2834 /* Do it! */
2835 switch (arch_apply_relocation
2836 (f, targsec, symsec, intsym, rel, value)) {
2837 case obj_reloc_ok:
2838 break;
2839
2840 case obj_reloc_overflow:
2841 errmsg = "Relocation overflow";
2842 goto bad_reloc;
2843 case obj_reloc_dangerous:
2844 errmsg = "Dangerous relocation";
2845 goto bad_reloc;
2846 case obj_reloc_unhandled:
2847 errmsg = "Unhandled relocation";
2848 bad_reloc:
2849 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002850 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002851 (long) ELFW(R_TYPE) (rel->r_info),
2852 strtab + extsym->st_name);
2853 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002854 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002855 (long) ELFW(R_TYPE) (rel->r_info));
2856 }
2857 ret = 0;
2858 break;
2859 }
2860 }
2861 }
2862
2863 /* Finally, take care of the patches. */
2864
2865 if (f->string_patches) {
2866 struct obj_string_patch *p;
2867 struct obj_section *strsec;
2868 ElfW(Addr) strsec_base;
2869 strsec = obj_find_section(f, ".kstrtab");
2870 strsec_base = strsec->header.sh_addr;
2871
2872 for (p = f->string_patches; p; p = p->next) {
2873 struct obj_section *targsec = f->sections[p->reloc_secidx];
2874 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2875 = strsec_base + p->string_offset;
2876 }
2877 }
2878
2879 if (f->symbol_patches) {
2880 struct obj_symbol_patch *p;
2881
2882 for (p = f->symbol_patches; p; p = p->next) {
2883 struct obj_section *targsec = f->sections[p->reloc_secidx];
2884 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2885 = obj_symbol_final_value(f, p->sym);
2886 }
2887 }
2888
2889 return ret;
2890}
2891
2892int obj_create_image(struct obj_file *f, char *image)
2893{
2894 struct obj_section *sec;
2895 ElfW(Addr) base = f->baseaddr;
2896
2897 for (sec = f->load_order; sec; sec = sec->load_next) {
2898 char *secimg;
2899
Eric Andersen2bf658d2001-02-24 20:01:53 +00002900 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002901 continue;
2902
2903 secimg = image + (sec->header.sh_addr - base);
2904
2905 /* Note that we allocated data for NOBITS sections earlier. */
2906 memcpy(secimg, sec->contents, sec->header.sh_size);
2907 }
2908
2909 return 1;
2910}
2911
2912/*======================================================================*/
2913
2914struct obj_file *obj_load(FILE * fp)
2915{
2916 struct obj_file *f;
2917 ElfW(Shdr) * section_headers;
2918 int shnum, i;
2919 char *shstrtab;
2920
2921 /* Read the file header. */
2922
2923 f = arch_new_file();
2924 memset(f, 0, sizeof(*f));
2925 f->symbol_cmp = strcmp;
2926 f->symbol_hash = obj_elf_hash;
2927 f->load_order_search_start = &f->load_order;
2928
2929 fseek(fp, 0, SEEK_SET);
2930 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002931 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002932 return NULL;
2933 }
2934
2935 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2936 || f->header.e_ident[EI_MAG1] != ELFMAG1
2937 || f->header.e_ident[EI_MAG2] != ELFMAG2
2938 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002939 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002940 return NULL;
2941 }
2942 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2943 || f->header.e_ident[EI_DATA] != ELFDATAM
2944 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2945 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002946 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002947 return NULL;
2948 }
2949 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002950 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002951 return NULL;
2952 }
2953
2954 /* Read the section headers. */
2955
2956 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002957 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 (unsigned long) f->header.e_shentsize,
2959 (unsigned long) sizeof(ElfW(Shdr)));
2960 return NULL;
2961 }
2962
2963 shnum = f->header.e_shnum;
2964 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2965 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2966
2967 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2968 fseek(fp, f->header.e_shoff, SEEK_SET);
2969 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002970 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002971 return NULL;
2972 }
2973
2974 /* Read the section data. */
2975
2976 for (i = 0; i < shnum; ++i) {
2977 struct obj_section *sec;
2978
2979 f->sections[i] = sec = arch_new_section();
2980 memset(sec, 0, sizeof(*sec));
2981
2982 sec->header = section_headers[i];
2983 sec->idx = i;
2984
Eric Andersen2bf658d2001-02-24 20:01:53 +00002985 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002986 case SHT_NULL:
2987 case SHT_NOTE:
2988 case SHT_NOBITS:
2989 /* ignore */
2990 break;
2991
2992 case SHT_PROGBITS:
2993 case SHT_SYMTAB:
2994 case SHT_STRTAB:
2995 case SHT_RELM:
2996 if (sec->header.sh_size > 0) {
2997 sec->contents = xmalloc(sec->header.sh_size);
2998 fseek(fp, sec->header.sh_offset, SEEK_SET);
2999 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003000 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003001 return NULL;
3002 }
3003 } else {
3004 sec->contents = NULL;
3005 }
3006 break;
3007
3008#if SHT_RELM == SHT_REL
3009 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003010 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003011 return NULL;
3012#else
3013 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003014 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 return NULL;
3016#endif
3017
3018 default:
3019 if (sec->header.sh_type >= SHT_LOPROC) {
3020 /* Assume processor specific section types are debug
3021 info and can safely be ignored. If this is ever not
3022 the case (Hello MIPS?), don't put ifdefs here but
3023 create an arch_load_proc_section(). */
3024 break;
3025 }
3026
Matt Kraaidd19c692001-01-31 19:00:21 +00003027 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003028 (long) sec->header.sh_type);
3029 return NULL;
3030 }
3031 }
3032
3033 /* Do what sort of interpretation as needed by each section. */
3034
3035 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3036
3037 for (i = 0; i < shnum; ++i) {
3038 struct obj_section *sec = f->sections[i];
3039 sec->name = shstrtab + sec->header.sh_name;
3040 }
3041
3042 for (i = 0; i < shnum; ++i) {
3043 struct obj_section *sec = f->sections[i];
3044
3045 if (sec->header.sh_flags & SHF_ALLOC)
3046 obj_insert_section_load_order(f, sec);
3047
3048 switch (sec->header.sh_type) {
3049 case SHT_SYMTAB:
3050 {
3051 unsigned long nsym, j;
3052 char *strtab;
3053 ElfW(Sym) * sym;
3054
3055 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003056 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003057 (unsigned long) sec->header.sh_entsize,
3058 (unsigned long) sizeof(ElfW(Sym)));
3059 return NULL;
3060 }
3061
3062 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3063 strtab = f->sections[sec->header.sh_link]->contents;
3064 sym = (ElfW(Sym) *) sec->contents;
3065
3066 /* Allocate space for a table of local symbols. */
3067 j = f->local_symtab_size = sec->header.sh_info;
3068 f->local_symtab = xmalloc(j *=
3069 sizeof(struct obj_symbol *));
3070 memset(f->local_symtab, 0, j);
3071
3072 /* Insert all symbols into the hash table. */
3073 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3074 const char *name;
3075 if (sym->st_name)
3076 name = strtab + sym->st_name;
3077 else
3078 name = f->sections[sym->st_shndx]->name;
3079
3080 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3081 sym->st_value, sym->st_size);
3082 }
3083 }
3084 break;
3085
3086 case SHT_RELM:
3087 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003088 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003089 (unsigned long) sec->header.sh_entsize,
3090 (unsigned long) sizeof(ElfW(RelM)));
3091 return NULL;
3092 }
3093 break;
3094 }
3095 }
3096
3097 return f;
3098}
3099
3100static void hide_special_symbols(struct obj_file *f)
3101{
3102 static const char *const specials[] = {
3103 "cleanup_module",
3104 "init_module",
3105 "kernel_version",
3106 NULL
3107 };
3108
3109 struct obj_symbol *sym;
3110 const char *const *p;
3111
3112 for (p = specials; *p; ++p)
3113 if ((sym = obj_find_symbol(f, *p)) != NULL)
3114 sym->info =
3115 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3116}
3117
3118
3119
3120extern int insmod_main( int argc, char **argv)
3121{
Eric Andersena18aaf12001-01-24 19:07:09 +00003122 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003123 int k_crcs;
3124 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003125 int len;
3126 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003127 unsigned long m_size;
3128 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003129 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003130 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003131 struct stat st;
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003133 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003134 int m_has_modinfo;
3135#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3136 int k_version;
3137 char k_strversion[STRVERSIONLEN];
3138 char m_strversion[STRVERSIONLEN];
3139 int m_version;
3140 int m_crcs;
3141#endif
3142
Erik Andersene49d5ec2000-02-08 19:58:47 +00003143 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003144 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003145 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003146 case 'f': /* force loading */
3147 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003148 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003149 case 'k': /* module loaded by kerneld, auto-cleanable */
3150 flag_autoclean = 1;
3151 break;
3152 case 'v': /* verbose output */
3153 flag_verbose = 1;
3154 break;
3155 case 'x': /* do not export externs */
3156 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003157 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003158 case 'o': /* name the output module */
3159 strncpy(m_name, optarg, BUFSIZ);
3160 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003161 case 'L': /* Stub warning */
3162 /* This is needed for compatibility with modprobe.
3163 * In theory, this does locking, but we don't do
3164 * that. So be careful and plan your life around not
3165 * loading the same module 50 times concurrently. */
3166 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003167 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003168 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003169 }
Erik Andersend387d011999-12-21 02:55:11 +00003170 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003171
3172 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003173 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003174 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003175
Erik Andersene49d5ec2000-02-08 19:58:47 +00003176 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003177 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003178 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003179 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003180 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003181 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003182 len = strlen(tmp);
3183
3184 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3185 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00003186 strncpy(m_fullName, tmp, len);
Eric Andersen114ad9c2001-01-26 01:52:14 +00003187 if (*m_name == '\0') {
3188 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003189 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003190 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003191
3192 /* Get a filedesc for the module */
Eric Andersen02b9f422001-02-15 19:07:43 +00003193 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3194 (fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003195 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00003196 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003197 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003198 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003199 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00003200 || ((fp = fopen(m_filename, "r")) == NULL))
3201 {
Matt Kraaidd19c692001-01-31 19:00:21 +00003202 error_msg("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00003203 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003204 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003205 } else
Matt Kraaidd19c692001-01-31 19:00:21 +00003206 error_msg_and_die("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003207 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00003208 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00003209
3210
Matt Kraaia9819b22000-12-22 01:48:07 +00003211 if ((f = obj_load(fp)) == NULL)
3212 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003213
Eric Andersen9f16d612000-06-12 23:11:16 +00003214 if (get_modinfo_value(f, "kernel_version") == NULL)
3215 m_has_modinfo = 0;
3216 else
3217 m_has_modinfo = 1;
3218
3219#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3220 /* Version correspondence? */
3221
3222 k_version = get_kernel_version(k_strversion);
3223 if (m_has_modinfo) {
3224 m_version = new_get_module_version(f, m_strversion);
3225 } else {
3226 m_version = old_get_module_version(f, m_strversion);
3227 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003228 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003229 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003230 goto out;
3231 }
3232 }
3233
3234 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3235 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003236 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003237 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003238 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003239 m_filename, m_strversion, k_strversion);
3240 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003241 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003242 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003243 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003244 m_filename, m_strversion, k_strversion);
3245 goto out;
3246 }
3247 }
3248 k_crcs = 0;
3249#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3250
3251 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3252
3253 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003254#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003255 if (!new_get_kernel_symbols())
3256 goto out;
3257 k_crcs = new_is_kernel_checksummed();
3258#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003259 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003260 goto out;
3261#endif
3262 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003263#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003264 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003265 goto out;
3266 k_crcs = old_is_kernel_checksummed();
3267#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003268 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003269 goto out;
3270#endif
3271 }
3272
3273#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3274 if (m_has_modinfo)
3275 m_crcs = new_is_module_checksummed(f);
3276 else
3277 m_crcs = old_is_module_checksummed(f);
3278
3279 if (m_crcs != k_crcs)
3280 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3281#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3282
Erik Andersene49d5ec2000-02-08 19:58:47 +00003283 /* Let the module know about the kernel symbols. */
3284 add_kernel_symbols(f);
3285
Eric Andersen9f16d612000-06-12 23:11:16 +00003286 /* Allocate common symbols, symbol tables, and string tables. */
3287
3288 if (k_new_syscalls
3289 ? !new_create_this_module(f, m_name)
3290 : !old_create_mod_use_count(f))
3291 {
3292 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003293 }
3294
Eric Andersen9f16d612000-06-12 23:11:16 +00003295 if (!obj_check_undefineds(f)) {
3296 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003297 }
3298 obj_allocate_commons(f);
3299
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003300 /* done with the module name, on to the optional var=value arguments */
3301 ++optind;
3302
Eric Andersen9f16d612000-06-12 23:11:16 +00003303 if (optind < argc) {
3304 if (m_has_modinfo
3305 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3306 : !old_process_module_arguments(f, argc - optind, argv + optind))
3307 {
3308 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003309 }
3310 }
3311
Eric Andersen9f16d612000-06-12 23:11:16 +00003312 arch_create_got(f);
3313 hide_special_symbols(f);
3314
3315 if (k_new_syscalls)
3316 new_create_module_ksymtab(f);
3317
Erik Andersene49d5ec2000-02-08 19:58:47 +00003318 /* Find current size of the module */
3319 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003320
3321
Erik Andersene49d5ec2000-02-08 19:58:47 +00003322 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003323 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003324 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003325 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 goto out;
3327 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003328 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003329 m_size);
3330 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003331 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003332 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003334 }
Erik Andersend387d011999-12-21 02:55:11 +00003335
Eric Andersen9f16d612000-06-12 23:11:16 +00003336 if (!obj_relocate(f, m_addr)) {
3337 delete_module(m_name);
3338 goto out;
3339 }
Erik Andersend387d011999-12-21 02:55:11 +00003340
Eric Andersen9f16d612000-06-12 23:11:16 +00003341 if (k_new_syscalls
3342 ? !new_init_module(m_name, f, m_size)
3343 : !old_init_module(m_name, f, m_size))
3344 {
3345 delete_module(m_name);
3346 goto out;
3347 }
3348
Matt Kraai3e856ce2000-12-01 02:55:13 +00003349 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003350
3351out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003352 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003353 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003354}