blob: abd639c6b366f4b429e632049fd111a9b1e60dba [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 Andersencbe31da2001-02-20 06:14:08 +000063#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Eric Andersen90fe7fe2001-02-20 20:47:08 +000065#if defined(__powerpc__)
66#define BB_USE_PLT_ENTRIES
67#define BB_PLT_ENTRY_SIZE 16
68#endif
69
70#if defined(__arm__)
71#define BB_USE_PLT_ENTRIES
72#define BB_PLT_ENTRY_SIZE 8
73#define BB_USE_GOT_ENTRIES
74#define BB_GOT_ENTRY_SIZE 8
75#endif
76
77#if defined(__sh__)
78#define BB_USE_GOT_ENTRIES
79#define BB_GOT_ENTRY_SIZE 4
80#endif
81
82#if defined(__i386__)
83#define BB_USE_GOT_ENTRIES
84#define BB_GOT_ENTRY_SIZE 4
85#endif
86
Eric Andersen2bf658d2001-02-24 20:01:53 +000087#if defined(__mips__)
88// neither used
89#endif
90
Eric Andersen9f16d612000-06-12 23:11:16 +000091//----------------------------------------------------------------------------
92//--------modutils module.h, lines 45-242
93//----------------------------------------------------------------------------
94
95/* Definitions for the Linux module syscall interface.
96 Copyright 1996, 1997 Linux International.
97
98 Contributed by Richard Henderson <rth@tamu.edu>
99
100 This file is part of the Linux modutils.
101
102 This program is free software; you can redistribute it and/or modify it
103 under the terms of the GNU General Public License as published by the
104 Free Software Foundation; either version 2 of the License, or (at your
105 option) any later version.
106
107 This program is distributed in the hope that it will be useful, but
108 WITHOUT ANY WARRANTY; without even the implied warranty of
109 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
110 General Public License for more details.
111
112 You should have received a copy of the GNU General Public License
113 along with this program; if not, write to the Free Software Foundation,
114 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
115
116
117#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000118static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000119
Eric Andersenacc77572001-04-05 06:24:28 +0000120#ident "$Id: insmod.c,v 1.56 2001/04/05 06:24:27 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000121
122/* This file contains the structures used by the 2.0 and 2.1 kernels.
123 We do not use the kernel headers directly because we do not wish
124 to be dependant on a particular kernel version to compile insmod. */
125
126
127/*======================================================================*/
128/* The structures used by Linux 2.0. */
129
130/* The symbol format used by get_kernel_syms(2). */
131struct old_kernel_sym
132{
133 unsigned long value;
134 char name[60];
135};
136
137struct old_module_ref
138{
139 unsigned long module; /* kernel addresses */
140 unsigned long next;
141};
142
143struct old_module_symbol
144{
145 unsigned long addr;
146 unsigned long name;
147};
148
149struct old_symbol_table
150{
151 int size; /* total, including string table!!! */
152 int n_symbols;
153 int n_refs;
154 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
155 struct old_module_ref ref[0]; /* actual size defined by n_refs */
156};
157
158struct old_mod_routines
159{
160 unsigned long init;
161 unsigned long cleanup;
162};
163
164struct old_module
165{
166 unsigned long next;
167 unsigned long ref; /* the list of modules that refer to me */
168 unsigned long symtab;
169 unsigned long name;
170 int size; /* size of module in pages */
171 unsigned long addr; /* address of module */
172 int state;
173 unsigned long cleanup; /* cleanup routine */
174};
175
176/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000177static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000178
179int get_kernel_syms(struct old_kernel_sym *);
180int old_sys_init_module(const char *name, char *code, unsigned codesize,
181 struct old_mod_routines *, struct old_symbol_table *);
182
183/*======================================================================*/
184/* For sizeof() which are related to the module platform and not to the
185 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
186
187#define tgt_sizeof_char sizeof(char)
188#define tgt_sizeof_short sizeof(short)
189#define tgt_sizeof_int sizeof(int)
190#define tgt_sizeof_long sizeof(long)
191#define tgt_sizeof_char_p sizeof(char *)
192#define tgt_sizeof_void_p sizeof(void *)
193#define tgt_long long
194
195#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
196#undef tgt_sizeof_long
197#undef tgt_sizeof_char_p
198#undef tgt_sizeof_void_p
199#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000200static const int tgt_sizeof_long = 8;
201static const int tgt_sizeof_char_p = 8;
202static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000203#define tgt_long long long
204#endif
205
206/*======================================================================*/
207/* The structures used in Linux 2.1. */
208
209/* Note: new_module_symbol does not use tgt_long intentionally */
210struct new_module_symbol
211{
212 unsigned long value;
213 unsigned long name;
214};
215
216struct new_module_persist;
217
218struct new_module_ref
219{
220 unsigned tgt_long dep; /* kernel addresses */
221 unsigned tgt_long ref;
222 unsigned tgt_long next_ref;
223};
224
225struct new_module
226{
227 unsigned tgt_long size_of_struct; /* == sizeof(module) */
228 unsigned tgt_long next;
229 unsigned tgt_long name;
230 unsigned tgt_long size;
231
232 tgt_long usecount;
233 unsigned tgt_long flags; /* AUTOCLEAN et al */
234
235 unsigned nsyms;
236 unsigned ndeps;
237
238 unsigned tgt_long syms;
239 unsigned tgt_long deps;
240 unsigned tgt_long refs;
241 unsigned tgt_long init;
242 unsigned tgt_long cleanup;
243 unsigned tgt_long ex_table_start;
244 unsigned tgt_long ex_table_end;
245#ifdef __alpha__
246 unsigned tgt_long gp;
247#endif
248 /* Everything after here is extension. */
249 unsigned tgt_long persist_start;
250 unsigned tgt_long persist_end;
251 unsigned tgt_long can_unload;
252 unsigned tgt_long runsize;
253};
254
255struct new_module_info
256{
257 unsigned long addr;
258 unsigned long size;
259 unsigned long flags;
260 long usecount;
261};
262
263/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000264static const int NEW_MOD_RUNNING = 1;
265static const int NEW_MOD_DELETED = 2;
266static const int NEW_MOD_AUTOCLEAN = 4;
267static const int NEW_MOD_VISITED = 8;
268static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000269
Eric Andersenacc77572001-04-05 06:24:28 +0000270int init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000271int query_module(const char *name, int which, void *buf, size_t bufsize,
272 size_t *ret);
273
274/* Values for query_module's which. */
275
Mark Whitley59ab0252001-01-23 22:30:04 +0000276static const int QM_MODULES = 1;
277static const int QM_DEPS = 2;
278static const int QM_REFS = 3;
279static const int QM_SYMBOLS = 4;
280static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000281
282/*======================================================================*/
283/* The system calls unchanged between 2.0 and 2.1. */
284
285unsigned long create_module(const char *, size_t);
286int delete_module(const char *);
287
288
289#endif /* module.h */
290
291//----------------------------------------------------------------------------
292//--------end of modutils module.h
293//----------------------------------------------------------------------------
294
295
296
297//----------------------------------------------------------------------------
298//--------modutils obj.h, lines 253-462
299//----------------------------------------------------------------------------
300
301/* Elf object file loading and relocation routines.
302 Copyright 1996, 1997 Linux International.
303
304 Contributed by Richard Henderson <rth@tamu.edu>
305
306 This file is part of the Linux modutils.
307
308 This program is free software; you can redistribute it and/or modify it
309 under the terms of the GNU General Public License as published by the
310 Free Software Foundation; either version 2 of the License, or (at your
311 option) any later version.
312
313 This program is distributed in the hope that it will be useful, but
314 WITHOUT ANY WARRANTY; without even the implied warranty of
315 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
316 General Public License for more details.
317
318 You should have received a copy of the GNU General Public License
319 along with this program; if not, write to the Free Software Foundation,
320 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
321
322
323#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000324static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000325
Eric Andersenacc77572001-04-05 06:24:28 +0000326#ident "$Id: insmod.c,v 1.56 2001/04/05 06:24:27 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000327
328/* The relocatable object is manipulated using elfin types. */
329
330#include <stdio.h>
331#include <elf.h>
332
333
334/* Machine-specific elf macros for i386 et al. */
335
Eric Andersenfe4208f2000-09-24 03:44:29 +0000336/* the SH changes have only been tested on the SH4 in =little endian= mode */
337/* I'm not sure about big endian, so let's warn: */
338
339#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
340#error insmod.c may require changes for use on big endian SH4/SH3
341#endif
342
343/* it may or may not work on the SH1/SH2... So let's error on those
344 also */
345#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
346#error insmod.c may require changes for non-SH3/SH4 use
347#endif
348
Eric Andersen9f16d612000-06-12 23:11:16 +0000349#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000350
351#if defined(__sh__)
352
353#define MATCH_MACHINE(x) (x == EM_SH)
354#define SHT_RELM SHT_RELA
355#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000356#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000357
Eric Andersen21adca72000-12-06 18:18:26 +0000358#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000359
Eric Andersen21adca72000-12-06 18:18:26 +0000360#define MATCH_MACHINE(x) (x == EM_ARM)
361#define SHT_RELM SHT_REL
362#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000363#define ELFDATAM ELFDATA2LSB
364
365#elif defined(__powerpc__)
366
367#define MATCH_MACHINE(x) (x == EM_PPC)
368#define SHT_RELM SHT_RELA
369#define Elf32_RelM Elf32_Rela
370#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000371
Eric Andersen2bf658d2001-02-24 20:01:53 +0000372#elif defined(__mips__)
373
Eric Andersen82bb8a22001-03-22 19:01:16 +0000374/* Account for ELF spec changes. */
375#ifndef EM_MIPS_RS3_LE
376#ifdef EM_MIPS_RS4_BE
377#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
378#else
379#define EM_MIPS_RS3_LE 10
380#endif
381#endif /* !EM_MIPS_RS3_LE */
382
Eric Andersen2bf658d2001-02-24 20:01:53 +0000383#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
384#define SHT_RELM SHT_REL
385#define Elf32_RelM Elf32_Rel
386#ifdef __MIPSEB__
387#define ELFDATAM ELFDATA2MSB
388#endif
389#ifdef __MIPSEL__
390#define ELFDATAM ELFDATA2LSB
391#endif
392
Eric Andersen21adca72000-12-06 18:18:26 +0000393#elif defined(__i386__)
394
395/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000396/* this is the previous behavior, but it does result in
397 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000398#ifndef EM_486
399#define MATCH_MACHINE(x) (x == EM_386)
400#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000401#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000402#endif
403
Eric Andersen9f16d612000-06-12 23:11:16 +0000404#define SHT_RELM SHT_REL
405#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000406#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000407
Eric Andersen21adca72000-12-06 18:18:26 +0000408#else
Eric Andersend5cad142001-01-26 02:23:57 +0000409#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000410#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000411
412#ifndef ElfW
413# if ELFCLASSM == ELFCLASS32
414# define ElfW(x) Elf32_ ## x
415# define ELFW(x) ELF32_ ## x
416# else
417# define ElfW(x) Elf64_ ## x
418# define ELFW(x) ELF64_ ## x
419# endif
420#endif
421
422/* For some reason this is missing from libc5. */
423#ifndef ELF32_ST_INFO
424# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
425#endif
426
427#ifndef ELF64_ST_INFO
428# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
429#endif
430
431struct obj_string_patch;
432struct obj_symbol_patch;
433
434struct obj_section
435{
436 ElfW(Shdr) header;
437 const char *name;
438 char *contents;
439 struct obj_section *load_next;
440 int idx;
441};
442
443struct obj_symbol
444{
445 struct obj_symbol *next; /* hash table link */
446 const char *name;
447 unsigned long value;
448 unsigned long size;
449 int secidx; /* the defining section index/module */
450 int info;
451 int ksymidx; /* for export to the kernel symtab */
452 int referenced; /* actually used in the link */
453};
454
455/* Hardcode the hash table size. We shouldn't be needing so many
456 symbols that we begin to degrade performance, and we get a big win
457 by giving the compiler a constant divisor. */
458
459#define HASH_BUCKETS 521
460
461struct obj_file
462{
463 ElfW(Ehdr) header;
464 ElfW(Addr) baseaddr;
465 struct obj_section **sections;
466 struct obj_section *load_order;
467 struct obj_section **load_order_search_start;
468 struct obj_string_patch *string_patches;
469 struct obj_symbol_patch *symbol_patches;
470 int (*symbol_cmp)(const char *, const char *);
471 unsigned long (*symbol_hash)(const char *);
472 unsigned long local_symtab_size;
473 struct obj_symbol **local_symtab;
474 struct obj_symbol *symtab[HASH_BUCKETS];
475};
476
477enum obj_reloc
478{
479 obj_reloc_ok,
480 obj_reloc_overflow,
481 obj_reloc_dangerous,
482 obj_reloc_unhandled
483};
484
485struct obj_string_patch
486{
487 struct obj_string_patch *next;
488 int reloc_secidx;
489 ElfW(Addr) reloc_offset;
490 ElfW(Addr) string_offset;
491};
492
493struct obj_symbol_patch
494{
495 struct obj_symbol_patch *next;
496 int reloc_secidx;
497 ElfW(Addr) reloc_offset;
498 struct obj_symbol *sym;
499};
500
501
502/* Generic object manipulation routines. */
503
504unsigned long obj_elf_hash(const char *);
505
506unsigned long obj_elf_hash_n(const char *, unsigned long len);
507
508struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
509 unsigned long symidx, int info, int secidx,
510 ElfW(Addr) value, unsigned long size);
511
512struct obj_symbol *obj_find_symbol (struct obj_file *f,
513 const char *name);
514
515ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
516 struct obj_symbol *sym);
517
518void obj_set_symbol_compare(struct obj_file *f,
519 int (*cmp)(const char *, const char *),
520 unsigned long (*hash)(const char *));
521
522struct obj_section *obj_find_section (struct obj_file *f,
523 const char *name);
524
525void obj_insert_section_load_order (struct obj_file *f,
526 struct obj_section *sec);
527
528struct obj_section *obj_create_alloced_section (struct obj_file *f,
529 const char *name,
530 unsigned long align,
531 unsigned long size);
532
533struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
534 const char *name,
535 unsigned long align,
536 unsigned long size);
537
538void *obj_extend_section (struct obj_section *sec, unsigned long more);
539
540int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
541 const char *string);
542
543int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
544 struct obj_symbol *sym);
545
546int obj_check_undefineds(struct obj_file *f);
547
548void obj_allocate_commons(struct obj_file *f);
549
550unsigned long obj_load_size (struct obj_file *f);
551
552int obj_relocate (struct obj_file *f, ElfW(Addr) base);
553
554struct obj_file *obj_load(FILE *f);
555
556int obj_create_image (struct obj_file *f, char *image);
557
558/* Architecture specific manipulation routines. */
559
560struct obj_file *arch_new_file (void);
561
562struct obj_section *arch_new_section (void);
563
564struct obj_symbol *arch_new_symbol (void);
565
566enum obj_reloc arch_apply_relocation (struct obj_file *f,
567 struct obj_section *targsec,
568 struct obj_section *symsec,
569 struct obj_symbol *sym,
570 ElfW(RelM) *rel, ElfW(Addr) value);
571
572int arch_create_got (struct obj_file *f);
573
574struct new_module;
575int arch_init_module (struct obj_file *f, struct new_module *);
576
577#endif /* obj.h */
578//----------------------------------------------------------------------------
579//--------end of modutils obj.h
580//----------------------------------------------------------------------------
581
582
583
584
Erik Andersen02104321999-12-17 18:57:34 +0000585
Erik Andersend387d011999-12-21 02:55:11 +0000586#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000587static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000588
Eric Andersen9f16d612000-06-12 23:11:16 +0000589/*======================================================================*/
590
591int flag_force_load = 0;
592int flag_autoclean = 0;
593int flag_verbose = 0;
594int flag_export = 1;
595
596
597/*======================================================================*/
598
Eric Andersenfe4208f2000-09-24 03:44:29 +0000599/* previously, these were named i386_* but since we could be
600 compiling for the sh, I've renamed them to the more general
601 arch_* These structures are the same between the x86 and SH,
602 and we can't support anything else right now anyway. In the
603 future maybe they should be #if defined'd */
604
Eric Andersen21adca72000-12-06 18:18:26 +0000605/* Done ;-) */
606
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000607
608
609#if defined(BB_USE_PLT_ENTRIES)
610struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000611{
612 int offset;
613 int allocated:1;
614 int inited:1; /* has been set up */
615};
616#endif
617
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000618#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000619struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000620 int offset;
621 unsigned offset_done:1;
622 unsigned reloc_done:1;
623};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000624#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000625
Eric Andersen2bf658d2001-02-24 20:01:53 +0000626#if defined(__mips__)
627struct mips_hi16
628{
629 struct mips_hi16 *next;
630 Elf32_Addr *addr;
631 Elf32_Addr value;
632};
633#endif
634
Eric Andersenfe4208f2000-09-24 03:44:29 +0000635struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000636 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000637#if defined(BB_USE_PLT_ENTRIES)
638 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000639#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000640#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000641 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000642#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000643#if defined(__mips__)
644 struct mips_hi16 *mips_hi16_list;
645#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000646};
647
Eric Andersenfe4208f2000-09-24 03:44:29 +0000648struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000649 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000650#if defined(BB_USE_PLT_ENTRIES)
651 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000652#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000653#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000654 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000655#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000656};
657
658
Eric Andersen9f16d612000-06-12 23:11:16 +0000659struct external_module {
660 const char *name;
661 ElfW(Addr) addr;
662 int used;
663 size_t nsyms;
664 struct new_module_symbol *syms;
665};
666
667struct new_module_symbol *ksyms;
668size_t nksyms;
669
670struct external_module *ext_modules;
671int n_ext_modules;
672int n_ext_modules_used;
673
Erik Andersend387d011999-12-21 02:55:11 +0000674
Erik Andersen02104321999-12-17 18:57:34 +0000675extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000676
Erik Andersen02104321999-12-17 18:57:34 +0000677
Eric Andersenfe4208f2000-09-24 03:44:29 +0000678/* This is kind of troublesome. See, we don't actually support
679 the m68k or the arm the same way we support i386 and (now)
680 sh. In doing my SH patch, I just assumed that whatever works
681 for i386 also works for m68k and arm since currently insmod.c
682 does nothing special for them. If this isn't true, the below
683 line is rather misleading IMHO, and someone should either
684 change it or add more proper architecture-dependent support
685 for these boys.
686
687 -- Bryan Rittmeyer <bryan@ixiacom.com> */
688
Eric Andersen23c1a182001-03-19 19:28:24 +0000689static char m_filename[BUFSIZ + 1];
690static char m_fullName[BUFSIZ + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000691
Eric Andersen9f16d612000-06-12 23:11:16 +0000692/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000693
Eric Andersen9f16d612000-06-12 23:11:16 +0000694
695static int findNamedModule(const char *fileName, struct stat *statbuf,
696 void *userDate)
697{
698 char *fullName = (char *) userDate;
699
700
701 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000702 return (FALSE);
703 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000704 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000705
706 if (tmp == NULL)
707 tmp = (char *) fileName;
708 else
709 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000710 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000711 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000712 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000713 return (FALSE);
714 }
Erik Andersend387d011999-12-21 02:55:11 +0000715 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000716 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000717}
718
Erik Andersen02104321999-12-17 18:57:34 +0000719
Eric Andersen9f16d612000-06-12 23:11:16 +0000720/*======================================================================*/
721
722struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000723{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000724 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000725 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000726
727#if defined(BB_USE_PLT_ENTRIES)
728 f->plt = NULL;
729#endif
730#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000731 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000732#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000733#if defined(__mips__)
734 f->mips_hi16_list = NULL;
735#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000736
Eric Andersen9f16d612000-06-12 23:11:16 +0000737 return &f->root;
738}
739
740struct obj_section *arch_new_section(void)
741{
742 return xmalloc(sizeof(struct obj_section));
743}
744
745struct obj_symbol *arch_new_symbol(void)
746{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000747 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000748 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000749
750#if defined(BB_USE_PLT_ENTRIES)
751 memset(&sym->pltent, 0, sizeof(sym->pltent));
752#endif
753#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755#endif
756
Eric Andersen9f16d612000-06-12 23:11:16 +0000757 return &sym->root;
758}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000759
Eric Andersen9f16d612000-06-12 23:11:16 +0000760enum obj_reloc
761arch_apply_relocation(struct obj_file *f,
762 struct obj_section *targsec,
763 struct obj_section *symsec,
764 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000765 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000766{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000767 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000768#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000769 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000770#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000771
Eric Andersen21adca72000-12-06 18:18:26 +0000772 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
773 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000774#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000775 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000776#endif
777#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000778 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000779 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000780 unsigned long *ip;
781#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000782 enum obj_reloc ret = obj_reloc_ok;
783
784 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000785
786/* even though these constants seem to be the same for
787 the i386 and the sh, we "#if define" them for clarity
788 and in case that ever changes */
789#if defined(__sh__)
790 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000791#elif defined(__arm__)
792 case R_ARM_NONE:
793#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000794 case R_386_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000795#elif defined(__powerpc__)
796 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000797#elif defined(__mips__)
798 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000799#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000800 break;
801
Eric Andersenfe4208f2000-09-24 03:44:29 +0000802#if defined(__sh__)
803 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000804#elif defined(__arm__)
805 case R_ARM_ABS32:
806#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000807 case R_386_32:
808#elif defined(__powerpc__)
809 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000810#elif defined(__mips__)
811 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000813 *loc += v;
814 break;
815
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816#if defined(__powerpc__)
817 case R_PPC_ADDR16_HA:
818 *(unsigned short *)loc = (v + 0x8000) >> 16;
819 break;
820
821 case R_PPC_ADDR16_HI:
822 *(unsigned short *)loc = v >> 16;
823 break;
824
825 case R_PPC_ADDR16_LO:
826 *(unsigned short *)loc = v;
827 break;
828#endif
829
Eric Andersen2bf658d2001-02-24 20:01:53 +0000830#if defined(__mips__)
831 case R_MIPS_26:
832 if (v % 4)
833 ret = obj_reloc_dangerous;
834 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
835 ret = obj_reloc_overflow;
836 *loc =
837 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
838 0x03ffffff);
839 break;
840
841 case R_MIPS_HI16:
842 {
843 struct mips_hi16 *n;
844
845 /* We cannot relocate this one now because we don't know the value
846 of the carry we need to add. Save the information, and let LO16
847 do the actual relocation. */
848 n = (struct mips_hi16 *) xmalloc(sizeof *n);
849 n->addr = loc;
850 n->value = v;
851 n->next = ifile->mips_hi16_list;
852 ifile->mips_hi16_list = n;
853 break;
854 }
855
856 case R_MIPS_LO16:
857 {
858 unsigned long insnlo = *loc;
859 Elf32_Addr val, vallo;
860
861 /* Sign extend the addend we extract from the lo insn. */
862 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
863
864 if (ifile->mips_hi16_list != NULL) {
865 struct mips_hi16 *l;
866
867 l = ifile->mips_hi16_list;
868 while (l != NULL) {
869 struct mips_hi16 *next;
870 unsigned long insn;
871
872 /* The value for the HI16 had best be the same. */
873 assert(v == l->value);
874
875 /* Do the HI16 relocation. Note that we actually don't
876 need to know anything about the LO16 itself, except where
877 to find the low 16 bits of the addend needed by the LO16. */
878 insn = *l->addr;
879 val =
880 ((insn & 0xffff) << 16) +
881 vallo;
882 val += v;
883
884 /* Account for the sign extension that will happen in the
885 low bits. */
886 val =
887 ((val >> 16) +
888 ((val & 0x8000) !=
889 0)) & 0xffff;
890
891 insn = (insn & ~0xffff) | val;
892 *l->addr = insn;
893
894 next = l->next;
895 free(l);
896 l = next;
897 }
898
899 ifile->mips_hi16_list = NULL;
900 }
901
902 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
903 val = v + vallo;
904 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
905 *loc = insnlo;
906 break;
907 }
908#endif
909
Eric Andersen21adca72000-12-06 18:18:26 +0000910#if defined(__arm__)
911#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000912 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000913 *loc += v - dot;
914 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000915#elif defined(__i386__)
916 case R_386_PLT32:
917 case R_386_PC32:
918 *loc += v - dot;
919 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000920#elif defined(__powerpc__)
921 case R_PPC_REL32:
922 *loc = v - dot;
923 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000924#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000925
Eric Andersenfe4208f2000-09-24 03:44:29 +0000926#if defined(__sh__)
927 case R_SH_PLT32:
928 *loc = v - dot;
929 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000930#elif defined(__i386__)
931#endif
932
933#if defined(BB_USE_PLT_ENTRIES)
934
935#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000936 case R_ARM_PC24:
937 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000938#endif
939#if defined(__powerpc__)
940 case R_PPC_REL24:
941#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000942 /* find the plt entry and initialize it if necessary */
943 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000944
945 pe = (struct arch_plt_entry*) &isym->pltent;
946
Eric Andersen21adca72000-12-06 18:18:26 +0000947 if (! pe->inited) {
948 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000949
950 /* generate some machine code */
951
952#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000953 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
954 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000955#endif
956#if defined(__powerpc__)
957 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
958 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
959 ip[2] = 0x7d6903a6; /* mtctr r11 */
960 ip[3] = 0x4e800420; /* bctr */
961#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000962 pe->inited = 1;
963 }
964
965 /* relative distance to target */
966 v -= dot;
967 /* if the target is too far away.... */
968 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
969 /* go via the plt */
970 v = plt + pe->offset - dot;
971 }
972 if (v & 3)
973 ret = obj_reloc_dangerous;
974
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000975 /* merge the offset into the instruction. */
976#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000977 /* Convert to words. */
978 v >>= 2;
979
Eric Andersen21adca72000-12-06 18:18:26 +0000980 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +0000981#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000982#if defined(__powerpc__)
983 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
984#endif
985 break;
986#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +0000987
Eric Andersen21adca72000-12-06 18:18:26 +0000988#if defined(__arm__)
989#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000990 case R_SH_GLOB_DAT:
991 case R_SH_JMP_SLOT:
992 *loc = v;
993 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000994#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000995 case R_386_GLOB_DAT:
996 case R_386_JMP_SLOT:
997 *loc = v;
998 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000999#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001000
Eric Andersen21adca72000-12-06 18:18:26 +00001001#if defined(__arm__)
1002#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001003 case R_SH_RELATIVE:
1004 *loc += f->baseaddr + rel->r_addend;
1005 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001006#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001007 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001008 *loc += f->baseaddr;
1009 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001010#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001011
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001012#if defined(BB_USE_GOT_ENTRIES)
1013
Eric Andersenfe4208f2000-09-24 03:44:29 +00001014#if defined(__sh__)
1015 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001016#elif defined(__arm__)
1017 case R_ARM_GOTPC:
1018#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001019 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001020#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001021 assert(got != 0);
1022#if defined(__sh__)
1023 *loc += got - dot + rel->r_addend;;
1024#elif defined(__i386__) || defined(__arm__)
1025 *loc += got - dot;
1026#endif
1027 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001028
Eric Andersenfe4208f2000-09-24 03:44:29 +00001029#if defined(__sh__)
1030 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001031#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001032 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001033#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001034 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001035#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001036 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001037 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001038 if (!isym->gotent.reloc_done) {
1039 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001040 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001041 }
Eric Andersen21adca72000-12-06 18:18:26 +00001042 /* make the reloc with_respect_to_.got */
1043#if defined(__sh__)
1044 *loc += isym->gotent.offset + rel->r_addend;
1045#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001046 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001047#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001048 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001049
Eric Andersen21adca72000-12-06 18:18:26 +00001050 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001051#if defined(__sh__)
1052 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001053#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001054 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001055#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001056 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001058 assert(got != 0);
1059 *loc += v - got;
1060 break;
1061
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001062#endif /* BB_USE_GOT_ENTRIES */
1063
Eric Andersen9f16d612000-06-12 23:11:16 +00001064 default:
Eric Andersen21125542000-12-13 16:41:29 +00001065 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001066 ret = obj_reloc_unhandled;
1067 break;
1068 }
1069
1070 return ret;
1071}
1072
1073int arch_create_got(struct obj_file *f)
1074{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001075#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001076 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001077 int i;
1078#if defined(BB_USE_GOT_ENTRIES)
1079 int got_offset = 0, gotneeded = 0;
1080#endif
1081#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001082 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001083#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001084 struct obj_section *relsec, *symsec, *strsec;
1085 ElfW(RelM) *rel, *relend;
1086 ElfW(Sym) *symtab, *extsym;
1087 const char *strtab, *name;
1088 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001089
Eric Andersen21adca72000-12-06 18:18:26 +00001090 for (i = 0; i < f->header.e_shnum; ++i) {
1091 relsec = f->sections[i];
1092 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001093 continue;
1094
Eric Andersen21adca72000-12-06 18:18:26 +00001095 symsec = f->sections[relsec->header.sh_link];
1096 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001097
Eric Andersen21adca72000-12-06 18:18:26 +00001098 rel = (ElfW(RelM) *) relsec->contents;
1099 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1100 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001101 strtab = (const char *) strsec->contents;
1102
1103 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001104 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001105
1106 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001107#if defined(__arm__)
1108 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001109 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001110#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001111 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001112 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001113#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001114 case R_386_GOT32:
1115 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001116#endif
1117
1118#if defined(__powerpc__)
1119 case R_PPC_REL24:
1120 pltneeded = 1;
1121 break;
1122#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001123
1124#if defined(__arm__)
1125 case R_ARM_PC24:
1126 case R_ARM_PLT32:
1127 pltneeded = 1;
1128 break;
1129
1130 case R_ARM_GOTPC:
1131 case R_ARM_GOTOFF:
1132 gotneeded = 1;
1133 if (got_offset == 0)
1134 got_offset = 4;
1135#elif defined(__sh__)
1136 case R_SH_GOTPC:
1137 case R_SH_GOTOFF:
1138 gotneeded = 1;
1139#elif defined(__i386__)
1140 case R_386_GOTPC:
1141 case R_386_GOTOFF:
1142 gotneeded = 1;
1143#endif
1144
1145 default:
1146 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001147 }
1148
Eric Andersen21adca72000-12-06 18:18:26 +00001149 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001150 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001151 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001152 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001153 }
1154 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001155#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001156 if (!intsym->gotent.offset_done) {
1157 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001158 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001159 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001160 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001161#endif
1162#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001163 if (pltneeded && intsym->pltent.allocated == 0) {
1164 intsym->pltent.allocated = 1;
1165 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001166 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001167 intsym->pltent.inited = 0;
1168 pltneeded = 0;
1169 }
1170#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001171 }
1172 }
Eric Andersen21adca72000-12-06 18:18:26 +00001173
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001174#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001175 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001176 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001177
Eric Andersene76c3b02001-04-05 03:14:39 +00001178 if (myrelsec) {
1179 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001180 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001181 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001182 BB_GOT_ENTRY_SIZE,
1183 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001184 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001185 }
1186
Eric Andersene76c3b02001-04-05 03:14:39 +00001187 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001188 }
Eric Andersen21adca72000-12-06 18:18:26 +00001189#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001190
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001191#if defined(BB_USE_PLT_ENTRIES)
1192 if (plt_offset)
1193 ifile->plt = obj_create_alloced_section(f, ".plt",
1194 BB_PLT_ENTRY_SIZE,
1195 plt_offset);
1196#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001197#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001198 return 1;
1199}
1200
1201int arch_init_module(struct obj_file *f, struct new_module *mod)
1202{
1203 return 1;
1204}
1205
1206
1207/*======================================================================*/
1208
1209/* Standard ELF hash function. */
1210inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1211{
1212 unsigned long h = 0;
1213 unsigned long g;
1214 unsigned char ch;
1215
1216 while (n > 0) {
1217 ch = *name++;
1218 h = (h << 4) + ch;
1219 if ((g = (h & 0xf0000000)) != 0) {
1220 h ^= g >> 24;
1221 h &= ~g;
1222 }
1223 n--;
1224 }
1225 return h;
1226}
1227
1228unsigned long obj_elf_hash(const char *name)
1229{
1230 return obj_elf_hash_n(name, strlen(name));
1231}
1232
1233#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1234/* Get the kernel version in the canonical integer form. */
1235
1236static int get_kernel_version(char str[STRVERSIONLEN])
1237{
1238 struct utsname uts_info;
1239 char *p, *q;
1240 int a, b, c;
1241
1242 if (uname(&uts_info) < 0)
1243 return -1;
1244 strncpy(str, uts_info.release, STRVERSIONLEN);
1245 p = uts_info.release;
1246
1247 a = strtoul(p, &p, 10);
1248 if (*p != '.')
1249 return -1;
1250 b = strtoul(p + 1, &p, 10);
1251 if (*p != '.')
1252 return -1;
1253 c = strtoul(p + 1, &q, 10);
1254 if (p + 1 == q)
1255 return -1;
1256
1257 return a << 16 | b << 8 | c;
1258}
1259
1260/* String comparison for non-co-versioned kernel and module. */
1261
1262static int ncv_strcmp(const char *a, const char *b)
1263{
1264 size_t alen = strlen(a), blen = strlen(b);
1265
1266 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1267 return strncmp(a, b, alen);
1268 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1269 return strncmp(a, b, blen);
1270 else
1271 return strcmp(a, b);
1272}
1273
1274/* String hashing for non-co-versioned kernel and module. Here
1275 we are simply forced to drop the crc from the hash. */
1276
1277static unsigned long ncv_symbol_hash(const char *str)
1278{
1279 size_t len = strlen(str);
1280 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1281 len -= 10;
1282 return obj_elf_hash_n(str, len);
1283}
1284
1285void
1286obj_set_symbol_compare(struct obj_file *f,
1287 int (*cmp) (const char *, const char *),
1288 unsigned long (*hash) (const char *))
1289{
1290 if (cmp)
1291 f->symbol_cmp = cmp;
1292 if (hash) {
1293 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1294 int i;
1295
1296 f->symbol_hash = hash;
1297
1298 memcpy(tmptab, f->symtab, sizeof(tmptab));
1299 memset(f->symtab, 0, sizeof(f->symtab));
1300
1301 for (i = 0; i < HASH_BUCKETS; ++i)
1302 for (sym = tmptab[i]; sym; sym = next) {
1303 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1304 next = sym->next;
1305 sym->next = f->symtab[h];
1306 f->symtab[h] = sym;
1307 }
1308 }
1309}
1310
1311#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1312
1313
1314struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1315 unsigned long symidx, int info,
1316 int secidx, ElfW(Addr) value,
1317 unsigned long size)
1318{
1319 struct obj_symbol *sym;
1320 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1321 int n_type = ELFW(ST_TYPE) (info);
1322 int n_binding = ELFW(ST_BIND) (info);
1323
1324 for (sym = f->symtab[hash]; sym; sym = sym->next)
1325 if (f->symbol_cmp(sym->name, name) == 0) {
1326 int o_secidx = sym->secidx;
1327 int o_info = sym->info;
1328 int o_type = ELFW(ST_TYPE) (o_info);
1329 int o_binding = ELFW(ST_BIND) (o_info);
1330
1331 /* A redefinition! Is it legal? */
1332
1333 if (secidx == SHN_UNDEF)
1334 return sym;
1335 else if (o_secidx == SHN_UNDEF)
1336 goto found;
1337 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1338 /* Cope with local and global symbols of the same name
1339 in the same object file, as might have been created
1340 by ld -r. The only reason locals are now seen at this
1341 level at all is so that we can do semi-sensible things
1342 with parameters. */
1343
1344 struct obj_symbol *nsym, **p;
1345
1346 nsym = arch_new_symbol();
1347 nsym->next = sym->next;
1348 nsym->ksymidx = -1;
1349
1350 /* Excise the old (local) symbol from the hash chain. */
1351 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1352 continue;
1353 *p = sym = nsym;
1354 goto found;
1355 } else if (n_binding == STB_LOCAL) {
1356 /* Another symbol of the same name has already been defined.
1357 Just add this to the local table. */
1358 sym = arch_new_symbol();
1359 sym->next = NULL;
1360 sym->ksymidx = -1;
1361 f->local_symtab[symidx] = sym;
1362 goto found;
1363 } else if (n_binding == STB_WEAK)
1364 return sym;
1365 else if (o_binding == STB_WEAK)
1366 goto found;
1367 /* Don't unify COMMON symbols with object types the programmer
1368 doesn't expect. */
1369 else if (secidx == SHN_COMMON
1370 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1371 return sym;
1372 else if (o_secidx == SHN_COMMON
1373 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1374 goto found;
1375 else {
1376 /* Don't report an error if the symbol is coming from
1377 the kernel or some external module. */
1378 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001379 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001380 return sym;
1381 }
1382 }
1383
1384 /* Completely new symbol. */
1385 sym = arch_new_symbol();
1386 sym->next = f->symtab[hash];
1387 f->symtab[hash] = sym;
1388 sym->ksymidx = -1;
1389
1390 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1391 f->local_symtab[symidx] = sym;
1392
1393 found:
1394 sym->name = name;
1395 sym->value = value;
1396 sym->size = size;
1397 sym->secidx = secidx;
1398 sym->info = info;
1399
1400 return sym;
1401}
1402
1403struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1404{
1405 struct obj_symbol *sym;
1406 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1407
1408 for (sym = f->symtab[hash]; sym; sym = sym->next)
1409 if (f->symbol_cmp(sym->name, name) == 0)
1410 return sym;
1411
1412 return NULL;
1413}
1414
1415ElfW(Addr)
1416 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1417{
1418 if (sym) {
1419 if (sym->secidx >= SHN_LORESERVE)
1420 return sym->value;
1421
1422 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1423 } else {
1424 /* As a special case, a NULL sym has value zero. */
1425 return 0;
1426 }
1427}
1428
1429struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1430{
1431 int i, n = f->header.e_shnum;
1432
1433 for (i = 0; i < n; ++i)
1434 if (strcmp(f->sections[i]->name, name) == 0)
1435 return f->sections[i];
1436
1437 return NULL;
1438}
1439
1440static int obj_load_order_prio(struct obj_section *a)
1441{
1442 unsigned long af, ac;
1443
1444 af = a->header.sh_flags;
1445
1446 ac = 0;
1447 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1448 strcmp(a->name + 5, ".init"))
1449 ac |= 32;
1450 if (af & SHF_ALLOC)
1451 ac |= 16;
1452 if (!(af & SHF_WRITE))
1453 ac |= 8;
1454 if (af & SHF_EXECINSTR)
1455 ac |= 4;
1456 if (a->header.sh_type != SHT_NOBITS)
1457 ac |= 2;
1458
1459 return ac;
1460}
1461
1462void
1463obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1464{
1465 struct obj_section **p;
1466 int prio = obj_load_order_prio(sec);
1467 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1468 if (obj_load_order_prio(*p) < prio)
1469 break;
1470 sec->load_next = *p;
1471 *p = sec;
1472}
1473
1474struct obj_section *obj_create_alloced_section(struct obj_file *f,
1475 const char *name,
1476 unsigned long align,
1477 unsigned long size)
1478{
1479 int newidx = f->header.e_shnum++;
1480 struct obj_section *sec;
1481
1482 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1483 f->sections[newidx] = sec = arch_new_section();
1484
1485 memset(sec, 0, sizeof(*sec));
1486 sec->header.sh_type = SHT_PROGBITS;
1487 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1488 sec->header.sh_size = size;
1489 sec->header.sh_addralign = align;
1490 sec->name = name;
1491 sec->idx = newidx;
1492 if (size)
1493 sec->contents = xmalloc(size);
1494
1495 obj_insert_section_load_order(f, sec);
1496
1497 return sec;
1498}
1499
1500struct obj_section *obj_create_alloced_section_first(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 sec->load_next = f->load_order;
1522 f->load_order = sec;
1523 if (f->load_order_search_start == &f->load_order)
1524 f->load_order_search_start = &sec->load_next;
1525
1526 return sec;
1527}
1528
1529void *obj_extend_section(struct obj_section *sec, unsigned long more)
1530{
1531 unsigned long oldsize = sec->header.sh_size;
1532 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1533 return sec->contents + oldsize;
1534}
1535
1536
1537
1538/* Conditionally add the symbols from the given symbol set to the
1539 new module. */
1540
1541static int
1542add_symbols_from(
1543 struct obj_file *f,
1544 int idx, struct new_module_symbol *syms, size_t nsyms)
1545{
1546 struct new_module_symbol *s;
1547 size_t i;
1548 int used = 0;
1549
1550 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1551
1552 /* Only add symbols that are already marked external. If we
1553 override locals we may cause problems for argument initialization.
1554 We will also create a false dependency on the module. */
1555 struct obj_symbol *sym;
1556
1557 sym = obj_find_symbol(f, (char *) s->name);
1558 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1559 sym = obj_add_symbol(f, (char *) s->name, -1,
1560 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1561 idx, s->value, 0);
1562 /* Did our symbol just get installed? If so, mark the
1563 module as "used". */
1564 if (sym->secidx == idx)
1565 used = 1;
1566 }
1567 }
1568
1569 return used;
1570}
1571
1572static void add_kernel_symbols(struct obj_file *f)
1573{
1574 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001575 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001576
1577 /* Add module symbols first. */
1578
1579 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1580 if (m->nsyms
1581 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1582 m->nsyms)) m->used = 1, ++nused;
1583
1584 n_ext_modules_used = nused;
1585
1586 /* And finally the symbols from the kernel proper. */
1587
1588 if (nksyms)
1589 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1590}
1591
1592static char *get_modinfo_value(struct obj_file *f, const char *key)
1593{
1594 struct obj_section *sec;
1595 char *p, *v, *n, *ep;
1596 size_t klen = strlen(key);
1597
1598 sec = obj_find_section(f, ".modinfo");
1599 if (sec == NULL)
1600 return NULL;
1601 p = sec->contents;
1602 ep = p + sec->header.sh_size;
1603 while (p < ep) {
1604 v = strchr(p, '=');
1605 n = strchr(p, '\0');
1606 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001607 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001608 return v + 1;
1609 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001610 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001611 return n;
1612 }
1613 p = n + 1;
1614 }
1615
1616 return NULL;
1617}
1618
1619
1620/*======================================================================*/
1621/* Functions relating to module loading in pre 2.1 kernels. */
1622
1623static int
1624old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1625{
1626 while (argc > 0) {
1627 char *p, *q;
1628 struct obj_symbol *sym;
1629 int *loc;
1630
1631 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001632 if ((q = strchr(p, '=')) == NULL) {
1633 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001634 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001635 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001636 *q++ = '\0';
1637
1638 sym = obj_find_symbol(f, p);
1639
1640 /* Also check that the parameter was not resolved from the kernel. */
1641 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001642 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001643 return 0;
1644 }
1645
1646 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1647
1648 /* Do C quoting if we begin with a ". */
1649 if (*q == '"') {
1650 char *r, *str;
1651
1652 str = alloca(strlen(q));
1653 for (r = str, q++; *q != '"'; ++q, ++r) {
1654 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001655 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001656 return 0;
1657 } else if (*q == '\\')
1658 switch (*++q) {
1659 case 'a':
1660 *r = '\a';
1661 break;
1662 case 'b':
1663 *r = '\b';
1664 break;
1665 case 'e':
1666 *r = '\033';
1667 break;
1668 case 'f':
1669 *r = '\f';
1670 break;
1671 case 'n':
1672 *r = '\n';
1673 break;
1674 case 'r':
1675 *r = '\r';
1676 break;
1677 case 't':
1678 *r = '\t';
1679 break;
1680
1681 case '0':
1682 case '1':
1683 case '2':
1684 case '3':
1685 case '4':
1686 case '5':
1687 case '6':
1688 case '7':
1689 {
1690 int c = *q - '0';
1691 if (q[1] >= '0' && q[1] <= '7') {
1692 c = (c * 8) + *++q - '0';
1693 if (q[1] >= '0' && q[1] <= '7')
1694 c = (c * 8) + *++q - '0';
1695 }
1696 *r = c;
1697 }
1698 break;
1699
1700 default:
1701 *r = *q;
1702 break;
1703 } else
1704 *r = *q;
1705 }
1706 *r = '\0';
1707 obj_string_patch(f, sym->secidx, sym->value, str);
1708 } else if (*q >= '0' && *q <= '9') {
1709 do
1710 *loc++ = strtoul(q, &q, 0);
1711 while (*q++ == ',');
1712 } else {
1713 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001714 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001715 char *r; /* To search for commas */
1716
1717 /* Break the string with comas */
1718 while ((r = strchr(q, ',')) != (char *) NULL) {
1719 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001720 obj_string_patch(f, sym->secidx, myloc - contents, q);
1721 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001722 q = r;
1723 }
1724
1725 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001726 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001727 }
1728
1729 argc--, argv++;
1730 }
1731
1732 return 1;
1733}
1734
1735#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1736static int old_is_module_checksummed(struct obj_file *f)
1737{
1738 return obj_find_symbol(f, "Using_Versions") != NULL;
1739}
1740/* Get the module's kernel version in the canonical integer form. */
1741
1742static int
1743old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1744{
1745 struct obj_symbol *sym;
1746 char *p, *q;
1747 int a, b, c;
1748
1749 sym = obj_find_symbol(f, "kernel_version");
1750 if (sym == NULL)
1751 return -1;
1752
1753 p = f->sections[sym->secidx]->contents + sym->value;
1754 strncpy(str, p, STRVERSIONLEN);
1755
1756 a = strtoul(p, &p, 10);
1757 if (*p != '.')
1758 return -1;
1759 b = strtoul(p + 1, &p, 10);
1760 if (*p != '.')
1761 return -1;
1762 c = strtoul(p + 1, &q, 10);
1763 if (p + 1 == q)
1764 return -1;
1765
1766 return a << 16 | b << 8 | c;
1767}
1768
1769#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1770
Eric Andersenf5d5e772001-01-24 23:34:48 +00001771#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001772
1773/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1774
Eric Andersen8c185f92000-09-22 00:38:07 +00001775static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001776{
1777 struct old_kernel_sym *ks, *k;
1778 struct new_module_symbol *s;
1779 struct external_module *mod;
1780 int nks, nms, nmod, i;
1781
1782 nks = get_kernel_syms(NULL);
1783 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001784 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001785 return 0;
1786 }
1787
1788 ks = k = xmalloc(nks * sizeof(*ks));
1789
1790 if (get_kernel_syms(ks) != nks) {
1791 perror("inconsistency with get_kernel_syms -- is someone else "
1792 "playing with modules?");
1793 free(ks);
1794 return 0;
1795 }
1796
1797 /* Collect the module information. */
1798
1799 mod = NULL;
1800 nmod = -1;
1801
1802 while (k->name[0] == '#' && k->name[1]) {
1803 struct old_kernel_sym *k2;
1804 struct new_module_symbol *s;
1805
1806 /* Find out how many symbols this module has. */
1807 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1808 continue;
1809 nms = k2 - k - 1;
1810
1811 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1812 mod[nmod].name = k->name + 1;
1813 mod[nmod].addr = k->value;
1814 mod[nmod].used = 0;
1815 mod[nmod].nsyms = nms;
1816 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1817
1818 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1819 s->name = (unsigned long) k->name;
1820 s->value = k->value;
1821 }
1822
1823 k = k2;
1824 }
1825
1826 ext_modules = mod;
1827 n_ext_modules = nmod + 1;
1828
1829 /* Now collect the symbols for the kernel proper. */
1830
1831 if (k->name[0] == '#')
1832 ++k;
1833
1834 nksyms = nms = nks - (k - ks);
1835 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1836
1837 for (i = 0; i < nms; ++i, ++s, ++k) {
1838 s->name = (unsigned long) k->name;
1839 s->value = k->value;
1840 }
1841
1842 return 1;
1843}
1844
1845/* Return the kernel symbol checksum version, or zero if not used. */
1846
1847static int old_is_kernel_checksummed(void)
1848{
1849 /* Using_Versions is the first symbol. */
1850 if (nksyms > 0
1851 && strcmp((char *) ksyms[0].name,
1852 "Using_Versions") == 0) return ksyms[0].value;
1853 else
1854 return 0;
1855}
1856
1857
1858static int old_create_mod_use_count(struct obj_file *f)
1859{
1860 struct obj_section *sec;
1861
1862 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1863 sizeof(long));
1864
1865 obj_add_symbol(f, "mod_use_count_", -1,
1866 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1867 sizeof(long));
1868
1869 return 1;
1870}
1871
1872static int
1873old_init_module(const char *m_name, struct obj_file *f,
1874 unsigned long m_size)
1875{
1876 char *image;
1877 struct old_mod_routines routines;
1878 struct old_symbol_table *symtab;
1879 int ret;
1880
1881 /* Create the symbol table */
1882 {
1883 int nsyms = 0, strsize = 0, total;
1884
1885 /* Size things first... */
1886 if (flag_export) {
1887 int i;
1888 for (i = 0; i < HASH_BUCKETS; ++i) {
1889 struct obj_symbol *sym;
1890 for (sym = f->symtab[i]; sym; sym = sym->next)
1891 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1892 && sym->secidx <= SHN_HIRESERVE)
1893 {
1894 sym->ksymidx = nsyms++;
1895 strsize += strlen(sym->name) + 1;
1896 }
1897 }
1898 }
1899
1900 total = (sizeof(struct old_symbol_table)
1901 + nsyms * sizeof(struct old_module_symbol)
1902 + n_ext_modules_used * sizeof(struct old_module_ref)
1903 + strsize);
1904 symtab = xmalloc(total);
1905 symtab->size = total;
1906 symtab->n_symbols = nsyms;
1907 symtab->n_refs = n_ext_modules_used;
1908
1909 if (flag_export && nsyms) {
1910 struct old_module_symbol *ksym;
1911 char *str;
1912 int i;
1913
1914 ksym = symtab->symbol;
1915 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1916 + n_ext_modules_used * sizeof(struct old_module_ref));
1917
1918 for (i = 0; i < HASH_BUCKETS; ++i) {
1919 struct obj_symbol *sym;
1920 for (sym = f->symtab[i]; sym; sym = sym->next)
1921 if (sym->ksymidx >= 0) {
1922 ksym->addr = obj_symbol_final_value(f, sym);
1923 ksym->name =
1924 (unsigned long) str - (unsigned long) symtab;
1925
Matt Kraai70a78552001-01-04 02:00:17 +00001926 strcpy(str, sym->name);
1927 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001928 ksym++;
1929 }
1930 }
1931 }
1932
1933 if (n_ext_modules_used) {
1934 struct old_module_ref *ref;
1935 int i;
1936
1937 ref = (struct old_module_ref *)
1938 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1939
1940 for (i = 0; i < n_ext_modules; ++i)
1941 if (ext_modules[i].used)
1942 ref++->module = ext_modules[i].addr;
1943 }
1944 }
1945
1946 /* Fill in routines. */
1947
1948 routines.init =
1949 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1950 routines.cleanup =
1951 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1952
1953 /* Whew! All of the initialization is complete. Collect the final
1954 module image and give it to the kernel. */
1955
1956 image = xmalloc(m_size);
1957 obj_create_image(f, image);
1958
1959 /* image holds the complete relocated module, accounting correctly for
1960 mod_use_count. However the old module kernel support assume that
1961 it is receiving something which does not contain mod_use_count. */
1962 ret = old_sys_init_module(m_name, image + sizeof(long),
1963 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1964 : 0), &routines, symtab);
1965 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001966 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001967
1968 free(image);
1969 free(symtab);
1970
1971 return ret == 0;
1972}
1973
1974#else
1975
1976#define old_create_mod_use_count(x) TRUE
1977#define old_init_module(x, y, z) TRUE
1978
Eric Andersenf5d5e772001-01-24 23:34:48 +00001979#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00001980
1981
1982
1983/*======================================================================*/
1984/* Functions relating to module loading after 2.1.18. */
1985
1986static int
1987new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1988{
1989 while (argc > 0) {
1990 char *p, *q, *key;
1991 struct obj_symbol *sym;
1992 char *contents, *loc;
1993 int min, max, n;
1994
1995 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001996 if ((q = strchr(p, '=')) == NULL) {
1997 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001998 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001999 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002000
2001 key = alloca(q - p + 6);
2002 memcpy(key, "parm_", 5);
2003 memcpy(key + 5, p, q - p);
2004 key[q - p + 5] = 0;
2005
2006 p = get_modinfo_value(f, key);
2007 key += 5;
2008 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002009 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002010 return 0;
2011 }
2012
2013 sym = obj_find_symbol(f, key);
2014
2015 /* Also check that the parameter was not resolved from the kernel. */
2016 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002017 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002018 return 0;
2019 }
2020
2021 if (isdigit(*p)) {
2022 min = strtoul(p, &p, 10);
2023 if (*p == '-')
2024 max = strtoul(p + 1, &p, 10);
2025 else
2026 max = min;
2027 } else
2028 min = max = 1;
2029
2030 contents = f->sections[sym->secidx]->contents;
2031 loc = contents + sym->value;
2032 n = (*++q != '\0');
2033
2034 while (1) {
2035 if ((*p == 's') || (*p == 'c')) {
2036 char *str;
2037
2038 /* Do C quoting if we begin with a ", else slurp the lot. */
2039 if (*q == '"') {
2040 char *r;
2041
2042 str = alloca(strlen(q));
2043 for (r = str, q++; *q != '"'; ++q, ++r) {
2044 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002045 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002046 key);
2047 return 0;
2048 } else if (*q == '\\')
2049 switch (*++q) {
2050 case 'a':
2051 *r = '\a';
2052 break;
2053 case 'b':
2054 *r = '\b';
2055 break;
2056 case 'e':
2057 *r = '\033';
2058 break;
2059 case 'f':
2060 *r = '\f';
2061 break;
2062 case 'n':
2063 *r = '\n';
2064 break;
2065 case 'r':
2066 *r = '\r';
2067 break;
2068 case 't':
2069 *r = '\t';
2070 break;
2071
2072 case '0':
2073 case '1':
2074 case '2':
2075 case '3':
2076 case '4':
2077 case '5':
2078 case '6':
2079 case '7':
2080 {
2081 int c = *q - '0';
2082 if (q[1] >= '0' && q[1] <= '7') {
2083 c = (c * 8) + *++q - '0';
2084 if (q[1] >= '0' && q[1] <= '7')
2085 c = (c * 8) + *++q - '0';
2086 }
2087 *r = c;
2088 }
2089 break;
2090
2091 default:
2092 *r = *q;
2093 break;
2094 } else
2095 *r = *q;
2096 }
2097 *r = '\0';
2098 ++q;
2099 } else {
2100 char *r;
2101
2102 /* In this case, the string is not quoted. We will break
2103 it using the coma (like for ints). If the user wants to
2104 include comas in a string, he just has to quote it */
2105
2106 /* Search the next coma */
2107 r = strchr(q, ',');
2108
2109 /* Found ? */
2110 if (r != (char *) NULL) {
2111 /* Recopy the current field */
2112 str = alloca(r - q + 1);
2113 memcpy(str, q, r - q);
2114
2115 /* I don't know if it is usefull, as the previous case
2116 doesn't null terminate the string ??? */
2117 str[r - q] = '\0';
2118
2119 /* Keep next fields */
2120 q = r;
2121 } else {
2122 /* last string */
2123 str = q;
2124 q = "";
2125 }
2126 }
2127
2128 if (*p == 's') {
2129 /* Normal string */
2130 obj_string_patch(f, sym->secidx, loc - contents, str);
2131 loc += tgt_sizeof_char_p;
2132 } else {
2133 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002134 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002135
2136 /* Get the size of each member */
2137 /* Probably we should do that outside the loop ? */
2138 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002139 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002140 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002141 return 0;
2142 }
2143 charssize = strtoul(p + 1, (char **) NULL, 10);
2144
2145 /* Check length */
2146 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002147 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002148 charssize - 1);
2149 return 0;
2150 }
2151
2152 /* Copy to location */
2153 strcpy((char *) loc, str);
2154 loc += charssize;
2155 }
2156 } else {
2157 long v = strtoul(q, &q, 0);
2158 switch (*p) {
2159 case 'b':
2160 *loc++ = v;
2161 break;
2162 case 'h':
2163 *(short *) loc = v;
2164 loc += tgt_sizeof_short;
2165 break;
2166 case 'i':
2167 *(int *) loc = v;
2168 loc += tgt_sizeof_int;
2169 break;
2170 case 'l':
2171 *(long *) loc = v;
2172 loc += tgt_sizeof_long;
2173 break;
2174
2175 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002176 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002177 return 0;
2178 }
2179 }
2180
2181 retry_end_of_value:
2182 switch (*q) {
2183 case '\0':
2184 goto end_of_arg;
2185
2186 case ' ':
2187 case '\t':
2188 case '\n':
2189 case '\r':
2190 ++q;
2191 goto retry_end_of_value;
2192
2193 case ',':
2194 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002195 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002196 return 0;
2197 }
2198 ++q;
2199 break;
2200
2201 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002202 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002203 return 0;
2204 }
2205 }
2206
2207 end_of_arg:
2208 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002209 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002210 return 0;
2211 }
2212
2213 argc--, argv++;
2214 }
2215
2216 return 1;
2217}
2218
2219#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2220static int new_is_module_checksummed(struct obj_file *f)
2221{
2222 const char *p = get_modinfo_value(f, "using_checksums");
2223 if (p)
2224 return atoi(p);
2225 else
2226 return 0;
2227}
2228
2229/* Get the module's kernel version in the canonical integer form. */
2230
2231static int
2232new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2233{
2234 char *p, *q;
2235 int a, b, c;
2236
2237 p = get_modinfo_value(f, "kernel_version");
2238 if (p == NULL)
2239 return -1;
2240 strncpy(str, p, STRVERSIONLEN);
2241
2242 a = strtoul(p, &p, 10);
2243 if (*p != '.')
2244 return -1;
2245 b = strtoul(p + 1, &p, 10);
2246 if (*p != '.')
2247 return -1;
2248 c = strtoul(p + 1, &q, 10);
2249 if (p + 1 == q)
2250 return -1;
2251
2252 return a << 16 | b << 8 | c;
2253}
2254
2255#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2256
2257
Eric Andersenf5d5e772001-01-24 23:34:48 +00002258#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002259
2260/* Fetch the loaded modules, and all currently exported symbols. */
2261
2262static int new_get_kernel_symbols(void)
2263{
2264 char *module_names, *mn;
2265 struct external_module *modules, *m;
2266 struct new_module_symbol *syms, *s;
2267 size_t ret, bufsize, nmod, nsyms, i, j;
2268
2269 /* Collect the loaded modules. */
2270
2271 module_names = xmalloc(bufsize = 256);
2272 retry_modules_load:
2273 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2274 if (errno == ENOSPC) {
2275 module_names = xrealloc(module_names, bufsize = ret);
2276 goto retry_modules_load;
2277 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002278 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002279 return 0;
2280 }
2281
2282 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002283
2284 /* Collect the modules' symbols. */
2285
Mark Whitley94fd4802001-03-12 23:08:34 +00002286 if (nmod){
2287 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2288 memset(modules, 0, nmod * sizeof(*modules));
2289 for (i = 0, mn = module_names, m = modules;
2290 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2291 struct new_module_info info;
2292
2293 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2294 if (errno == ENOENT) {
2295 /* The module was removed out from underneath us. */
2296 continue;
2297 }
2298 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002299 return 0;
2300 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002301
2302 syms = xmalloc(bufsize = 1024);
2303 retry_mod_sym_load:
2304 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2305 switch (errno) {
2306 case ENOSPC:
2307 syms = xrealloc(syms, bufsize = ret);
2308 goto retry_mod_sym_load;
2309 case ENOENT:
2310 /* The module was removed out from underneath us. */
2311 continue;
2312 default:
2313 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2314 return 0;
2315 }
2316 }
2317 nsyms = ret;
2318
2319 m->name = mn;
2320 m->addr = info.addr;
2321 m->nsyms = nsyms;
2322 m->syms = syms;
2323
2324 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2325 s->name += (unsigned long) syms;
2326 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002327 }
2328 }
2329
2330 /* Collect the kernel's symbols. */
2331
2332 syms = xmalloc(bufsize = 16 * 1024);
2333 retry_kern_sym_load:
2334 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2335 if (errno == ENOSPC) {
2336 syms = xrealloc(syms, bufsize = ret);
2337 goto retry_kern_sym_load;
2338 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002339 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002340 return 0;
2341 }
2342 nksyms = nsyms = ret;
2343 ksyms = syms;
2344
2345 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2346 s->name += (unsigned long) syms;
2347 }
2348 return 1;
2349}
2350
2351
2352/* Return the kernel symbol checksum version, or zero if not used. */
2353
2354static int new_is_kernel_checksummed(void)
2355{
2356 struct new_module_symbol *s;
2357 size_t i;
2358
2359 /* Using_Versions is not the first symbol, but it should be in there. */
2360
2361 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2362 if (strcmp((char *) s->name, "Using_Versions") == 0)
2363 return s->value;
2364
2365 return 0;
2366}
2367
2368
2369static int new_create_this_module(struct obj_file *f, const char *m_name)
2370{
2371 struct obj_section *sec;
2372
2373 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2374 sizeof(struct new_module));
2375 memset(sec->contents, 0, sizeof(struct new_module));
2376
2377 obj_add_symbol(f, "__this_module", -1,
2378 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2379 sizeof(struct new_module));
2380
2381 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2382 m_name);
2383
2384 return 1;
2385}
2386
2387
2388static int new_create_module_ksymtab(struct obj_file *f)
2389{
2390 struct obj_section *sec;
2391 int i;
2392
2393 /* We must always add the module references. */
2394
2395 if (n_ext_modules_used) {
2396 struct new_module_ref *dep;
2397 struct obj_symbol *tm;
2398
2399 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2400 (sizeof(struct new_module_ref)
2401 * n_ext_modules_used));
2402 if (!sec)
2403 return 0;
2404
2405 tm = obj_find_symbol(f, "__this_module");
2406 dep = (struct new_module_ref *) sec->contents;
2407 for (i = 0; i < n_ext_modules; ++i)
2408 if (ext_modules[i].used) {
2409 dep->dep = ext_modules[i].addr;
2410 obj_symbol_patch(f, sec->idx,
2411 (char *) &dep->ref - sec->contents, tm);
2412 dep->next_ref = 0;
2413 ++dep;
2414 }
2415 }
2416
2417 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2418 size_t nsyms;
2419 int *loaded;
2420
2421 sec =
2422 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2423 0);
2424
2425 /* We don't want to export symbols residing in sections that
2426 aren't loaded. There are a number of these created so that
2427 we make sure certain module options don't appear twice. */
2428
2429 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2430 while (--i >= 0)
2431 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2432
2433 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2434 struct obj_symbol *sym;
2435 for (sym = f->symtab[i]; sym; sym = sym->next)
2436 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2437 && sym->secidx <= SHN_HIRESERVE
2438 && (sym->secidx >= SHN_LORESERVE
2439 || loaded[sym->secidx])) {
2440 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2441
2442 obj_symbol_patch(f, sec->idx, ofs, sym);
2443 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2444 sym->name);
2445
2446 nsyms++;
2447 }
2448 }
2449
2450 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2451 }
2452
2453 return 1;
2454}
2455
2456
2457static int
2458new_init_module(const char *m_name, struct obj_file *f,
2459 unsigned long m_size)
2460{
2461 struct new_module *module;
2462 struct obj_section *sec;
2463 void *image;
2464 int ret;
2465 tgt_long m_addr;
2466
2467 sec = obj_find_section(f, ".this");
2468 module = (struct new_module *) sec->contents;
2469 m_addr = sec->header.sh_addr;
2470
2471 module->size_of_struct = sizeof(*module);
2472 module->size = m_size;
2473 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2474
2475 sec = obj_find_section(f, "__ksymtab");
2476 if (sec && sec->header.sh_size) {
2477 module->syms = sec->header.sh_addr;
2478 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2479 }
2480
2481 if (n_ext_modules_used) {
2482 sec = obj_find_section(f, ".kmodtab");
2483 module->deps = sec->header.sh_addr;
2484 module->ndeps = n_ext_modules_used;
2485 }
2486
2487 module->init =
2488 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2489 module->cleanup =
2490 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2491
2492 sec = obj_find_section(f, "__ex_table");
2493 if (sec) {
2494 module->ex_table_start = sec->header.sh_addr;
2495 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2496 }
2497
2498 sec = obj_find_section(f, ".text.init");
2499 if (sec) {
2500 module->runsize = sec->header.sh_addr - m_addr;
2501 }
2502 sec = obj_find_section(f, ".data.init");
2503 if (sec) {
2504 if (!module->runsize ||
2505 module->runsize > sec->header.sh_addr - m_addr)
2506 module->runsize = sec->header.sh_addr - m_addr;
2507 }
2508
2509 if (!arch_init_module(f, module))
2510 return 0;
2511
2512 /* Whew! All of the initialization is complete. Collect the final
2513 module image and give it to the kernel. */
2514
2515 image = xmalloc(m_size);
2516 obj_create_image(f, image);
2517
Eric Andersenacc77572001-04-05 06:24:28 +00002518 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002519 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002520 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002521
2522 free(image);
2523
2524 return ret == 0;
2525}
2526
2527#else
2528
2529#define new_init_module(x, y, z) TRUE
2530#define new_create_this_module(x, y) 0
2531#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002532#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002533
Eric Andersenf5d5e772001-01-24 23:34:48 +00002534#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002535
2536
2537/*======================================================================*/
2538
2539int
2540obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2541 const char *string)
2542{
2543 struct obj_string_patch *p;
2544 struct obj_section *strsec;
2545 size_t len = strlen(string) + 1;
2546 char *loc;
2547
2548 p = xmalloc(sizeof(*p));
2549 p->next = f->string_patches;
2550 p->reloc_secidx = secidx;
2551 p->reloc_offset = offset;
2552 f->string_patches = p;
2553
2554 strsec = obj_find_section(f, ".kstrtab");
2555 if (strsec == NULL) {
2556 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2557 p->string_offset = 0;
2558 loc = strsec->contents;
2559 } else {
2560 p->string_offset = strsec->header.sh_size;
2561 loc = obj_extend_section(strsec, len);
2562 }
2563 memcpy(loc, string, len);
2564
2565 return 1;
2566}
2567
2568int
2569obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2570 struct obj_symbol *sym)
2571{
2572 struct obj_symbol_patch *p;
2573
2574 p = xmalloc(sizeof(*p));
2575 p->next = f->symbol_patches;
2576 p->reloc_secidx = secidx;
2577 p->reloc_offset = offset;
2578 p->sym = sym;
2579 f->symbol_patches = p;
2580
2581 return 1;
2582}
2583
2584int obj_check_undefineds(struct obj_file *f)
2585{
2586 unsigned long i;
2587 int ret = 1;
2588
2589 for (i = 0; i < HASH_BUCKETS; ++i) {
2590 struct obj_symbol *sym;
2591 for (sym = f->symtab[i]; sym; sym = sym->next)
2592 if (sym->secidx == SHN_UNDEF) {
2593 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2594 sym->secidx = SHN_ABS;
2595 sym->value = 0;
2596 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002597 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002598 ret = 0;
2599 }
2600 }
2601 }
2602
2603 return ret;
2604}
2605
2606void obj_allocate_commons(struct obj_file *f)
2607{
2608 struct common_entry {
2609 struct common_entry *next;
2610 struct obj_symbol *sym;
2611 } *common_head = NULL;
2612
2613 unsigned long i;
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_COMMON) {
2619 /* Collect all COMMON symbols and sort them by size so as to
2620 minimize space wasted by alignment requirements. */
2621 {
2622 struct common_entry **p, *n;
2623 for (p = &common_head; *p; p = &(*p)->next)
2624 if (sym->size <= (*p)->sym->size)
2625 break;
2626
2627 n = alloca(sizeof(*n));
2628 n->next = *p;
2629 n->sym = sym;
2630 *p = n;
2631 }
2632 }
2633 }
2634
2635 for (i = 1; i < f->local_symtab_size; ++i) {
2636 struct obj_symbol *sym = f->local_symtab[i];
2637 if (sym && sym->secidx == SHN_COMMON) {
2638 struct common_entry **p, *n;
2639 for (p = &common_head; *p; p = &(*p)->next)
2640 if (sym == (*p)->sym)
2641 break;
2642 else if (sym->size < (*p)->sym->size) {
2643 n = alloca(sizeof(*n));
2644 n->next = *p;
2645 n->sym = sym;
2646 *p = n;
2647 break;
2648 }
2649 }
2650 }
2651
2652 if (common_head) {
2653 /* Find the bss section. */
2654 for (i = 0; i < f->header.e_shnum; ++i)
2655 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2656 break;
2657
2658 /* If for some reason there hadn't been one, create one. */
2659 if (i == f->header.e_shnum) {
2660 struct obj_section *sec;
2661
2662 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2663 f->sections[i] = sec = arch_new_section();
2664 f->header.e_shnum = i + 1;
2665
2666 memset(sec, 0, sizeof(*sec));
2667 sec->header.sh_type = SHT_PROGBITS;
2668 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2669 sec->name = ".bss";
2670 sec->idx = i;
2671 }
2672
2673 /* Allocate the COMMONS. */
2674 {
2675 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2676 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2677 struct common_entry *c;
2678
2679 for (c = common_head; c; c = c->next) {
2680 ElfW(Addr) align = c->sym->value;
2681
2682 if (align > max_align)
2683 max_align = align;
2684 if (bss_size & (align - 1))
2685 bss_size = (bss_size | (align - 1)) + 1;
2686
2687 c->sym->secidx = i;
2688 c->sym->value = bss_size;
2689
2690 bss_size += c->sym->size;
2691 }
2692
2693 f->sections[i]->header.sh_size = bss_size;
2694 f->sections[i]->header.sh_addralign = max_align;
2695 }
2696 }
2697
2698 /* For the sake of patch relocation and parameter initialization,
2699 allocate zeroed data for NOBITS sections now. Note that after
2700 this we cannot assume NOBITS are really empty. */
2701 for (i = 0; i < f->header.e_shnum; ++i) {
2702 struct obj_section *s = f->sections[i];
2703 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002704 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002705 s->contents = memset(xmalloc(s->header.sh_size),
2706 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002707 else
2708 s->contents = NULL;
2709
Eric Andersen9f16d612000-06-12 23:11:16 +00002710 s->header.sh_type = SHT_PROGBITS;
2711 }
2712 }
2713}
2714
2715unsigned long obj_load_size(struct obj_file *f)
2716{
2717 unsigned long dot = 0;
2718 struct obj_section *sec;
2719
2720 /* Finalize the positions of the sections relative to one another. */
2721
2722 for (sec = f->load_order; sec; sec = sec->load_next) {
2723 ElfW(Addr) align;
2724
2725 align = sec->header.sh_addralign;
2726 if (align && (dot & (align - 1)))
2727 dot = (dot | (align - 1)) + 1;
2728
2729 sec->header.sh_addr = dot;
2730 dot += sec->header.sh_size;
2731 }
2732
2733 return dot;
2734}
2735
2736int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2737{
2738 int i, n = f->header.e_shnum;
2739 int ret = 1;
2740
2741 /* Finalize the addresses of the sections. */
2742
2743 f->baseaddr = base;
2744 for (i = 0; i < n; ++i)
2745 f->sections[i]->header.sh_addr += base;
2746
2747 /* And iterate over all of the relocations. */
2748
2749 for (i = 0; i < n; ++i) {
2750 struct obj_section *relsec, *symsec, *targsec, *strsec;
2751 ElfW(RelM) * rel, *relend;
2752 ElfW(Sym) * symtab;
2753 const char *strtab;
2754
2755 relsec = f->sections[i];
2756 if (relsec->header.sh_type != SHT_RELM)
2757 continue;
2758
2759 symsec = f->sections[relsec->header.sh_link];
2760 targsec = f->sections[relsec->header.sh_info];
2761 strsec = f->sections[symsec->header.sh_link];
2762
2763 rel = (ElfW(RelM) *) relsec->contents;
2764 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2765 symtab = (ElfW(Sym) *) symsec->contents;
2766 strtab = (const char *) strsec->contents;
2767
2768 for (; rel < relend; ++rel) {
2769 ElfW(Addr) value = 0;
2770 struct obj_symbol *intsym = NULL;
2771 unsigned long symndx;
2772 ElfW(Sym) * extsym = 0;
2773 const char *errmsg;
2774
2775 /* Attempt to find a value to use for this relocation. */
2776
2777 symndx = ELFW(R_SYM) (rel->r_info);
2778 if (symndx) {
2779 /* Note we've already checked for undefined symbols. */
2780
2781 extsym = &symtab[symndx];
2782 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2783 /* Local symbols we look up in the local table to be sure
2784 we get the one that is really intended. */
2785 intsym = f->local_symtab[symndx];
2786 } else {
2787 /* Others we look up in the hash table. */
2788 const char *name;
2789 if (extsym->st_name)
2790 name = strtab + extsym->st_name;
2791 else
2792 name = f->sections[extsym->st_shndx]->name;
2793 intsym = obj_find_symbol(f, name);
2794 }
2795
2796 value = obj_symbol_final_value(f, intsym);
2797 intsym->referenced = 1;
2798 }
2799#if SHT_RELM == SHT_RELA
2800#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2801 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2802 if (!extsym || !extsym->st_name ||
2803 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2804#endif
2805 value += rel->r_addend;
2806#endif
2807
2808 /* Do it! */
2809 switch (arch_apply_relocation
2810 (f, targsec, symsec, intsym, rel, value)) {
2811 case obj_reloc_ok:
2812 break;
2813
2814 case obj_reloc_overflow:
2815 errmsg = "Relocation overflow";
2816 goto bad_reloc;
2817 case obj_reloc_dangerous:
2818 errmsg = "Dangerous relocation";
2819 goto bad_reloc;
2820 case obj_reloc_unhandled:
2821 errmsg = "Unhandled relocation";
2822 bad_reloc:
2823 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002824 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002825 (long) ELFW(R_TYPE) (rel->r_info),
2826 strtab + extsym->st_name);
2827 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002828 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002829 (long) ELFW(R_TYPE) (rel->r_info));
2830 }
2831 ret = 0;
2832 break;
2833 }
2834 }
2835 }
2836
2837 /* Finally, take care of the patches. */
2838
2839 if (f->string_patches) {
2840 struct obj_string_patch *p;
2841 struct obj_section *strsec;
2842 ElfW(Addr) strsec_base;
2843 strsec = obj_find_section(f, ".kstrtab");
2844 strsec_base = strsec->header.sh_addr;
2845
2846 for (p = f->string_patches; p; p = p->next) {
2847 struct obj_section *targsec = f->sections[p->reloc_secidx];
2848 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2849 = strsec_base + p->string_offset;
2850 }
2851 }
2852
2853 if (f->symbol_patches) {
2854 struct obj_symbol_patch *p;
2855
2856 for (p = f->symbol_patches; p; p = p->next) {
2857 struct obj_section *targsec = f->sections[p->reloc_secidx];
2858 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2859 = obj_symbol_final_value(f, p->sym);
2860 }
2861 }
2862
2863 return ret;
2864}
2865
2866int obj_create_image(struct obj_file *f, char *image)
2867{
2868 struct obj_section *sec;
2869 ElfW(Addr) base = f->baseaddr;
2870
2871 for (sec = f->load_order; sec; sec = sec->load_next) {
2872 char *secimg;
2873
Eric Andersen2bf658d2001-02-24 20:01:53 +00002874 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002875 continue;
2876
2877 secimg = image + (sec->header.sh_addr - base);
2878
2879 /* Note that we allocated data for NOBITS sections earlier. */
2880 memcpy(secimg, sec->contents, sec->header.sh_size);
2881 }
2882
2883 return 1;
2884}
2885
2886/*======================================================================*/
2887
2888struct obj_file *obj_load(FILE * fp)
2889{
2890 struct obj_file *f;
2891 ElfW(Shdr) * section_headers;
2892 int shnum, i;
2893 char *shstrtab;
2894
2895 /* Read the file header. */
2896
2897 f = arch_new_file();
2898 memset(f, 0, sizeof(*f));
2899 f->symbol_cmp = strcmp;
2900 f->symbol_hash = obj_elf_hash;
2901 f->load_order_search_start = &f->load_order;
2902
2903 fseek(fp, 0, SEEK_SET);
2904 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002905 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002906 return NULL;
2907 }
2908
2909 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2910 || f->header.e_ident[EI_MAG1] != ELFMAG1
2911 || f->header.e_ident[EI_MAG2] != ELFMAG2
2912 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002913 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002914 return NULL;
2915 }
2916 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2917 || f->header.e_ident[EI_DATA] != ELFDATAM
2918 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2919 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002920 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002921 return NULL;
2922 }
2923 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002924 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002925 return NULL;
2926 }
2927
2928 /* Read the section headers. */
2929
2930 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002931 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00002932 (unsigned long) f->header.e_shentsize,
2933 (unsigned long) sizeof(ElfW(Shdr)));
2934 return NULL;
2935 }
2936
2937 shnum = f->header.e_shnum;
2938 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2939 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2940
2941 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2942 fseek(fp, f->header.e_shoff, SEEK_SET);
2943 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002944 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002945 return NULL;
2946 }
2947
2948 /* Read the section data. */
2949
2950 for (i = 0; i < shnum; ++i) {
2951 struct obj_section *sec;
2952
2953 f->sections[i] = sec = arch_new_section();
2954 memset(sec, 0, sizeof(*sec));
2955
2956 sec->header = section_headers[i];
2957 sec->idx = i;
2958
Eric Andersen2bf658d2001-02-24 20:01:53 +00002959 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002960 case SHT_NULL:
2961 case SHT_NOTE:
2962 case SHT_NOBITS:
2963 /* ignore */
2964 break;
2965
2966 case SHT_PROGBITS:
2967 case SHT_SYMTAB:
2968 case SHT_STRTAB:
2969 case SHT_RELM:
2970 if (sec->header.sh_size > 0) {
2971 sec->contents = xmalloc(sec->header.sh_size);
2972 fseek(fp, sec->header.sh_offset, SEEK_SET);
2973 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002974 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002975 return NULL;
2976 }
2977 } else {
2978 sec->contents = NULL;
2979 }
2980 break;
2981
2982#if SHT_RELM == SHT_REL
2983 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00002984 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002985 return NULL;
2986#else
2987 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00002988 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002989 return NULL;
2990#endif
2991
2992 default:
2993 if (sec->header.sh_type >= SHT_LOPROC) {
2994 /* Assume processor specific section types are debug
2995 info and can safely be ignored. If this is ever not
2996 the case (Hello MIPS?), don't put ifdefs here but
2997 create an arch_load_proc_section(). */
2998 break;
2999 }
3000
Matt Kraaidd19c692001-01-31 19:00:21 +00003001 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003002 (long) sec->header.sh_type);
3003 return NULL;
3004 }
3005 }
3006
3007 /* Do what sort of interpretation as needed by each section. */
3008
3009 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3010
3011 for (i = 0; i < shnum; ++i) {
3012 struct obj_section *sec = f->sections[i];
3013 sec->name = shstrtab + sec->header.sh_name;
3014 }
3015
3016 for (i = 0; i < shnum; ++i) {
3017 struct obj_section *sec = f->sections[i];
3018
3019 if (sec->header.sh_flags & SHF_ALLOC)
3020 obj_insert_section_load_order(f, sec);
3021
3022 switch (sec->header.sh_type) {
3023 case SHT_SYMTAB:
3024 {
3025 unsigned long nsym, j;
3026 char *strtab;
3027 ElfW(Sym) * sym;
3028
3029 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003030 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003031 (unsigned long) sec->header.sh_entsize,
3032 (unsigned long) sizeof(ElfW(Sym)));
3033 return NULL;
3034 }
3035
3036 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3037 strtab = f->sections[sec->header.sh_link]->contents;
3038 sym = (ElfW(Sym) *) sec->contents;
3039
3040 /* Allocate space for a table of local symbols. */
3041 j = f->local_symtab_size = sec->header.sh_info;
3042 f->local_symtab = xmalloc(j *=
3043 sizeof(struct obj_symbol *));
3044 memset(f->local_symtab, 0, j);
3045
3046 /* Insert all symbols into the hash table. */
3047 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3048 const char *name;
3049 if (sym->st_name)
3050 name = strtab + sym->st_name;
3051 else
3052 name = f->sections[sym->st_shndx]->name;
3053
3054 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3055 sym->st_value, sym->st_size);
3056 }
3057 }
3058 break;
3059
3060 case SHT_RELM:
3061 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003062 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003063 (unsigned long) sec->header.sh_entsize,
3064 (unsigned long) sizeof(ElfW(RelM)));
3065 return NULL;
3066 }
3067 break;
3068 }
3069 }
3070
3071 return f;
3072}
3073
3074static void hide_special_symbols(struct obj_file *f)
3075{
3076 static const char *const specials[] = {
3077 "cleanup_module",
3078 "init_module",
3079 "kernel_version",
3080 NULL
3081 };
3082
3083 struct obj_symbol *sym;
3084 const char *const *p;
3085
3086 for (p = specials; *p; ++p)
3087 if ((sym = obj_find_symbol(f, *p)) != NULL)
3088 sym->info =
3089 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3090}
3091
3092
3093
3094extern int insmod_main( int argc, char **argv)
3095{
Eric Andersena18aaf12001-01-24 19:07:09 +00003096 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003097 int k_crcs;
3098 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003099 int len;
3100 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003101 unsigned long m_size;
3102 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003103 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003104 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003105 struct stat st;
Eric Andersen9f16d612000-06-12 23:11:16 +00003106 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003107 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003108 int m_has_modinfo;
3109#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3110 int k_version;
3111 char k_strversion[STRVERSIONLEN];
3112 char m_strversion[STRVERSIONLEN];
3113 int m_version;
3114 int m_crcs;
3115#endif
3116
Erik Andersene49d5ec2000-02-08 19:58:47 +00003117 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003118 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003119 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003120 case 'f': /* force loading */
3121 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003122 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003123 case 'k': /* module loaded by kerneld, auto-cleanable */
3124 flag_autoclean = 1;
3125 break;
3126 case 'v': /* verbose output */
3127 flag_verbose = 1;
3128 break;
3129 case 'x': /* do not export externs */
3130 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003131 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003132 case 'o': /* name the output module */
3133 strncpy(m_name, optarg, BUFSIZ);
3134 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003135 case 'L': /* Stub warning */
3136 /* This is needed for compatibility with modprobe.
3137 * In theory, this does locking, but we don't do
3138 * that. So be careful and plan your life around not
3139 * loading the same module 50 times concurrently. */
3140 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003141 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003142 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003143 }
Erik Andersend387d011999-12-21 02:55:11 +00003144 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003145
3146 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003147 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003148 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003149
Erik Andersene49d5ec2000-02-08 19:58:47 +00003150 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003151 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003152 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003153 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003154 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003155 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003156 len = strlen(tmp);
3157
3158 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3159 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00003160 strncpy(m_fullName, tmp, len);
Eric Andersen114ad9c2001-01-26 01:52:14 +00003161 if (*m_name == '\0') {
3162 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003163 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003164 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003165
3166 /* Get a filedesc for the module */
Eric Andersen02b9f422001-02-15 19:07:43 +00003167 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3168 (fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003169 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00003170 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003171 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003172 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003173 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00003174 || ((fp = fopen(m_filename, "r")) == NULL))
3175 {
Matt Kraaidd19c692001-01-31 19:00:21 +00003176 error_msg("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00003177 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003178 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003179 } else
Matt Kraaidd19c692001-01-31 19:00:21 +00003180 error_msg_and_die("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003181 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00003182 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00003183
3184
Matt Kraaia9819b22000-12-22 01:48:07 +00003185 if ((f = obj_load(fp)) == NULL)
3186 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003187
Eric Andersen9f16d612000-06-12 23:11:16 +00003188 if (get_modinfo_value(f, "kernel_version") == NULL)
3189 m_has_modinfo = 0;
3190 else
3191 m_has_modinfo = 1;
3192
3193#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3194 /* Version correspondence? */
3195
3196 k_version = get_kernel_version(k_strversion);
3197 if (m_has_modinfo) {
3198 m_version = new_get_module_version(f, m_strversion);
3199 } else {
3200 m_version = old_get_module_version(f, m_strversion);
3201 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003202 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003203 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003204 goto out;
3205 }
3206 }
3207
3208 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3209 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003210 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003211 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003212 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003213 m_filename, m_strversion, k_strversion);
3214 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003215 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003216 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003217 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003218 m_filename, m_strversion, k_strversion);
3219 goto out;
3220 }
3221 }
3222 k_crcs = 0;
3223#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3224
3225 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3226
3227 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003228#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003229 if (!new_get_kernel_symbols())
3230 goto out;
3231 k_crcs = new_is_kernel_checksummed();
3232#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003233 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003234 goto out;
3235#endif
3236 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003237#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003238 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003239 goto out;
3240 k_crcs = old_is_kernel_checksummed();
3241#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003242 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003243 goto out;
3244#endif
3245 }
3246
3247#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3248 if (m_has_modinfo)
3249 m_crcs = new_is_module_checksummed(f);
3250 else
3251 m_crcs = old_is_module_checksummed(f);
3252
3253 if (m_crcs != k_crcs)
3254 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3255#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3256
Erik Andersene49d5ec2000-02-08 19:58:47 +00003257 /* Let the module know about the kernel symbols. */
3258 add_kernel_symbols(f);
3259
Eric Andersen9f16d612000-06-12 23:11:16 +00003260 /* Allocate common symbols, symbol tables, and string tables. */
3261
3262 if (k_new_syscalls
3263 ? !new_create_this_module(f, m_name)
3264 : !old_create_mod_use_count(f))
3265 {
3266 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003267 }
3268
Eric Andersen9f16d612000-06-12 23:11:16 +00003269 if (!obj_check_undefineds(f)) {
3270 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003271 }
3272 obj_allocate_commons(f);
3273
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003274 /* done with the module name, on to the optional var=value arguments */
3275 ++optind;
3276
Eric Andersen9f16d612000-06-12 23:11:16 +00003277 if (optind < argc) {
3278 if (m_has_modinfo
3279 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3280 : !old_process_module_arguments(f, argc - optind, argv + optind))
3281 {
3282 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003283 }
3284 }
3285
Eric Andersen9f16d612000-06-12 23:11:16 +00003286 arch_create_got(f);
3287 hide_special_symbols(f);
3288
3289 if (k_new_syscalls)
3290 new_create_module_ksymtab(f);
3291
Erik Andersene49d5ec2000-02-08 19:58:47 +00003292 /* Find current size of the module */
3293 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003294
3295
Erik Andersene49d5ec2000-02-08 19:58:47 +00003296 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003297 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003298 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003299 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003300 goto out;
3301 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003302 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003303 m_size);
3304 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003305 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003306 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003307 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003308 }
Erik Andersend387d011999-12-21 02:55:11 +00003309
Eric Andersen9f16d612000-06-12 23:11:16 +00003310 if (!obj_relocate(f, m_addr)) {
3311 delete_module(m_name);
3312 goto out;
3313 }
Erik Andersend387d011999-12-21 02:55:11 +00003314
Eric Andersen9f16d612000-06-12 23:11:16 +00003315 if (k_new_syscalls
3316 ? !new_init_module(m_name, f, m_size)
3317 : !old_init_module(m_name, f, m_size))
3318 {
3319 delete_module(m_name);
3320 goto out;
3321 }
3322
Matt Kraai3e856ce2000-12-01 02:55:13 +00003323 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003324
3325out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003326 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003327 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003328}