blob: c6642a0527a82c352f998f22a5f153085d61030c [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 Andersen64c8b172001-04-05 07:33:10 +000065#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
66# define new_sys_init_module init_module
67#else
68# define old_sys_init_module init_module
69#endif
70
Eric Andersen90fe7fe2001-02-20 20:47:08 +000071#if defined(__powerpc__)
72#define BB_USE_PLT_ENTRIES
73#define BB_PLT_ENTRY_SIZE 16
74#endif
75
76#if defined(__arm__)
77#define BB_USE_PLT_ENTRIES
78#define BB_PLT_ENTRY_SIZE 8
79#define BB_USE_GOT_ENTRIES
80#define BB_GOT_ENTRY_SIZE 8
81#endif
82
83#if defined(__sh__)
84#define BB_USE_GOT_ENTRIES
85#define BB_GOT_ENTRY_SIZE 4
86#endif
87
88#if defined(__i386__)
89#define BB_USE_GOT_ENTRIES
90#define BB_GOT_ENTRY_SIZE 4
91#endif
92
Eric Andersen2bf658d2001-02-24 20:01:53 +000093#if defined(__mips__)
94// neither used
95#endif
96
Eric Andersen9f16d612000-06-12 23:11:16 +000097//----------------------------------------------------------------------------
98//--------modutils module.h, lines 45-242
99//----------------------------------------------------------------------------
100
101/* Definitions for the Linux module syscall interface.
102 Copyright 1996, 1997 Linux International.
103
104 Contributed by Richard Henderson <rth@tamu.edu>
105
106 This file is part of the Linux modutils.
107
108 This program is free software; you can redistribute it and/or modify it
109 under the terms of the GNU General Public License as published by the
110 Free Software Foundation; either version 2 of the License, or (at your
111 option) any later version.
112
113 This program is distributed in the hope that it will be useful, but
114 WITHOUT ANY WARRANTY; without even the implied warranty of
115 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
116 General Public License for more details.
117
118 You should have received a copy of the GNU General Public License
119 along with this program; if not, write to the Free Software Foundation,
120 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
121
122
123#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000124static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000125
Eric Andersenf2278152001-04-24 21:41:41 +0000126#ident "$Id: insmod.c,v 1.58 2001/04/24 21:41:41 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000127
128/* This file contains the structures used by the 2.0 and 2.1 kernels.
129 We do not use the kernel headers directly because we do not wish
130 to be dependant on a particular kernel version to compile insmod. */
131
132
133/*======================================================================*/
134/* The structures used by Linux 2.0. */
135
136/* The symbol format used by get_kernel_syms(2). */
137struct old_kernel_sym
138{
139 unsigned long value;
140 char name[60];
141};
142
143struct old_module_ref
144{
145 unsigned long module; /* kernel addresses */
146 unsigned long next;
147};
148
149struct old_module_symbol
150{
151 unsigned long addr;
152 unsigned long name;
153};
154
155struct old_symbol_table
156{
157 int size; /* total, including string table!!! */
158 int n_symbols;
159 int n_refs;
160 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
161 struct old_module_ref ref[0]; /* actual size defined by n_refs */
162};
163
164struct old_mod_routines
165{
166 unsigned long init;
167 unsigned long cleanup;
168};
169
170struct old_module
171{
172 unsigned long next;
173 unsigned long ref; /* the list of modules that refer to me */
174 unsigned long symtab;
175 unsigned long name;
176 int size; /* size of module in pages */
177 unsigned long addr; /* address of module */
178 int state;
179 unsigned long cleanup; /* cleanup routine */
180};
181
182/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000183static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000184
185int get_kernel_syms(struct old_kernel_sym *);
186int old_sys_init_module(const char *name, char *code, unsigned codesize,
187 struct old_mod_routines *, struct old_symbol_table *);
188
189/*======================================================================*/
190/* For sizeof() which are related to the module platform and not to the
191 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
192
193#define tgt_sizeof_char sizeof(char)
194#define tgt_sizeof_short sizeof(short)
195#define tgt_sizeof_int sizeof(int)
196#define tgt_sizeof_long sizeof(long)
197#define tgt_sizeof_char_p sizeof(char *)
198#define tgt_sizeof_void_p sizeof(void *)
199#define tgt_long long
200
201#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
202#undef tgt_sizeof_long
203#undef tgt_sizeof_char_p
204#undef tgt_sizeof_void_p
205#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000206static const int tgt_sizeof_long = 8;
207static const int tgt_sizeof_char_p = 8;
208static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000209#define tgt_long long long
210#endif
211
212/*======================================================================*/
213/* The structures used in Linux 2.1. */
214
215/* Note: new_module_symbol does not use tgt_long intentionally */
216struct new_module_symbol
217{
218 unsigned long value;
219 unsigned long name;
220};
221
222struct new_module_persist;
223
224struct new_module_ref
225{
226 unsigned tgt_long dep; /* kernel addresses */
227 unsigned tgt_long ref;
228 unsigned tgt_long next_ref;
229};
230
231struct new_module
232{
233 unsigned tgt_long size_of_struct; /* == sizeof(module) */
234 unsigned tgt_long next;
235 unsigned tgt_long name;
236 unsigned tgt_long size;
237
238 tgt_long usecount;
239 unsigned tgt_long flags; /* AUTOCLEAN et al */
240
241 unsigned nsyms;
242 unsigned ndeps;
243
244 unsigned tgt_long syms;
245 unsigned tgt_long deps;
246 unsigned tgt_long refs;
247 unsigned tgt_long init;
248 unsigned tgt_long cleanup;
249 unsigned tgt_long ex_table_start;
250 unsigned tgt_long ex_table_end;
251#ifdef __alpha__
252 unsigned tgt_long gp;
253#endif
254 /* Everything after here is extension. */
255 unsigned tgt_long persist_start;
256 unsigned tgt_long persist_end;
257 unsigned tgt_long can_unload;
258 unsigned tgt_long runsize;
259};
260
261struct new_module_info
262{
263 unsigned long addr;
264 unsigned long size;
265 unsigned long flags;
266 long usecount;
267};
268
269/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000270static const int NEW_MOD_RUNNING = 1;
271static const int NEW_MOD_DELETED = 2;
272static const int NEW_MOD_AUTOCLEAN = 4;
273static const int NEW_MOD_VISITED = 8;
274static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000275
Eric Andersen64c8b172001-04-05 07:33:10 +0000276int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000277int query_module(const char *name, int which, void *buf, size_t bufsize,
278 size_t *ret);
279
280/* Values for query_module's which. */
281
Mark Whitley59ab0252001-01-23 22:30:04 +0000282static const int QM_MODULES = 1;
283static const int QM_DEPS = 2;
284static const int QM_REFS = 3;
285static const int QM_SYMBOLS = 4;
286static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000287
288/*======================================================================*/
289/* The system calls unchanged between 2.0 and 2.1. */
290
291unsigned long create_module(const char *, size_t);
292int delete_module(const char *);
293
294
295#endif /* module.h */
296
297//----------------------------------------------------------------------------
298//--------end of modutils module.h
299//----------------------------------------------------------------------------
300
301
302
303//----------------------------------------------------------------------------
304//--------modutils obj.h, lines 253-462
305//----------------------------------------------------------------------------
306
307/* Elf object file loading and relocation routines.
308 Copyright 1996, 1997 Linux International.
309
310 Contributed by Richard Henderson <rth@tamu.edu>
311
312 This file is part of the Linux modutils.
313
314 This program is free software; you can redistribute it and/or modify it
315 under the terms of the GNU General Public License as published by the
316 Free Software Foundation; either version 2 of the License, or (at your
317 option) any later version.
318
319 This program is distributed in the hope that it will be useful, but
320 WITHOUT ANY WARRANTY; without even the implied warranty of
321 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
322 General Public License for more details.
323
324 You should have received a copy of the GNU General Public License
325 along with this program; if not, write to the Free Software Foundation,
326 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
327
328
329#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000330static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000331
Eric Andersenf2278152001-04-24 21:41:41 +0000332#ident "$Id: insmod.c,v 1.58 2001/04/24 21:41:41 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000333
334/* The relocatable object is manipulated using elfin types. */
335
336#include <stdio.h>
337#include <elf.h>
338
339
340/* Machine-specific elf macros for i386 et al. */
341
Eric Andersenfe4208f2000-09-24 03:44:29 +0000342/* the SH changes have only been tested on the SH4 in =little endian= mode */
343/* I'm not sure about big endian, so let's warn: */
344
345#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
346#error insmod.c may require changes for use on big endian SH4/SH3
347#endif
348
349/* it may or may not work on the SH1/SH2... So let's error on those
350 also */
351#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
352#error insmod.c may require changes for non-SH3/SH4 use
353#endif
354
Eric Andersen9f16d612000-06-12 23:11:16 +0000355#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000356
357#if defined(__sh__)
358
359#define MATCH_MACHINE(x) (x == EM_SH)
360#define SHT_RELM SHT_RELA
361#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000362#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000363
Eric Andersen21adca72000-12-06 18:18:26 +0000364#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000365
Eric Andersen21adca72000-12-06 18:18:26 +0000366#define MATCH_MACHINE(x) (x == EM_ARM)
367#define SHT_RELM SHT_REL
368#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000369#define ELFDATAM ELFDATA2LSB
370
371#elif defined(__powerpc__)
372
373#define MATCH_MACHINE(x) (x == EM_PPC)
374#define SHT_RELM SHT_RELA
375#define Elf32_RelM Elf32_Rela
376#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000377
Eric Andersen2bf658d2001-02-24 20:01:53 +0000378#elif defined(__mips__)
379
Eric Andersen82bb8a22001-03-22 19:01:16 +0000380/* Account for ELF spec changes. */
381#ifndef EM_MIPS_RS3_LE
382#ifdef EM_MIPS_RS4_BE
383#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
384#else
385#define EM_MIPS_RS3_LE 10
386#endif
387#endif /* !EM_MIPS_RS3_LE */
388
Eric Andersen2bf658d2001-02-24 20:01:53 +0000389#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
390#define SHT_RELM SHT_REL
391#define Elf32_RelM Elf32_Rel
392#ifdef __MIPSEB__
393#define ELFDATAM ELFDATA2MSB
394#endif
395#ifdef __MIPSEL__
396#define ELFDATAM ELFDATA2LSB
397#endif
398
Eric Andersen21adca72000-12-06 18:18:26 +0000399#elif defined(__i386__)
400
401/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000402/* this is the previous behavior, but it does result in
403 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000404#ifndef EM_486
405#define MATCH_MACHINE(x) (x == EM_386)
406#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000407#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000408#endif
409
Eric Andersen9f16d612000-06-12 23:11:16 +0000410#define SHT_RELM SHT_REL
411#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000412#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000413
Eric Andersen21adca72000-12-06 18:18:26 +0000414#else
Eric Andersend5cad142001-01-26 02:23:57 +0000415#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000416#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000417
418#ifndef ElfW
419# if ELFCLASSM == ELFCLASS32
420# define ElfW(x) Elf32_ ## x
421# define ELFW(x) ELF32_ ## x
422# else
423# define ElfW(x) Elf64_ ## x
424# define ELFW(x) ELF64_ ## x
425# endif
426#endif
427
428/* For some reason this is missing from libc5. */
429#ifndef ELF32_ST_INFO
430# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
431#endif
432
433#ifndef ELF64_ST_INFO
434# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
435#endif
436
437struct obj_string_patch;
438struct obj_symbol_patch;
439
440struct obj_section
441{
442 ElfW(Shdr) header;
443 const char *name;
444 char *contents;
445 struct obj_section *load_next;
446 int idx;
447};
448
449struct obj_symbol
450{
451 struct obj_symbol *next; /* hash table link */
452 const char *name;
453 unsigned long value;
454 unsigned long size;
455 int secidx; /* the defining section index/module */
456 int info;
457 int ksymidx; /* for export to the kernel symtab */
458 int referenced; /* actually used in the link */
459};
460
461/* Hardcode the hash table size. We shouldn't be needing so many
462 symbols that we begin to degrade performance, and we get a big win
463 by giving the compiler a constant divisor. */
464
465#define HASH_BUCKETS 521
466
467struct obj_file
468{
469 ElfW(Ehdr) header;
470 ElfW(Addr) baseaddr;
471 struct obj_section **sections;
472 struct obj_section *load_order;
473 struct obj_section **load_order_search_start;
474 struct obj_string_patch *string_patches;
475 struct obj_symbol_patch *symbol_patches;
476 int (*symbol_cmp)(const char *, const char *);
477 unsigned long (*symbol_hash)(const char *);
478 unsigned long local_symtab_size;
479 struct obj_symbol **local_symtab;
480 struct obj_symbol *symtab[HASH_BUCKETS];
481};
482
483enum obj_reloc
484{
485 obj_reloc_ok,
486 obj_reloc_overflow,
487 obj_reloc_dangerous,
488 obj_reloc_unhandled
489};
490
491struct obj_string_patch
492{
493 struct obj_string_patch *next;
494 int reloc_secidx;
495 ElfW(Addr) reloc_offset;
496 ElfW(Addr) string_offset;
497};
498
499struct obj_symbol_patch
500{
501 struct obj_symbol_patch *next;
502 int reloc_secidx;
503 ElfW(Addr) reloc_offset;
504 struct obj_symbol *sym;
505};
506
507
508/* Generic object manipulation routines. */
509
510unsigned long obj_elf_hash(const char *);
511
512unsigned long obj_elf_hash_n(const char *, unsigned long len);
513
514struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
515 unsigned long symidx, int info, int secidx,
516 ElfW(Addr) value, unsigned long size);
517
518struct obj_symbol *obj_find_symbol (struct obj_file *f,
519 const char *name);
520
521ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
522 struct obj_symbol *sym);
523
524void obj_set_symbol_compare(struct obj_file *f,
525 int (*cmp)(const char *, const char *),
526 unsigned long (*hash)(const char *));
527
528struct obj_section *obj_find_section (struct obj_file *f,
529 const char *name);
530
531void obj_insert_section_load_order (struct obj_file *f,
532 struct obj_section *sec);
533
534struct obj_section *obj_create_alloced_section (struct obj_file *f,
535 const char *name,
536 unsigned long align,
537 unsigned long size);
538
539struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
540 const char *name,
541 unsigned long align,
542 unsigned long size);
543
544void *obj_extend_section (struct obj_section *sec, unsigned long more);
545
546int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
547 const char *string);
548
549int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
550 struct obj_symbol *sym);
551
552int obj_check_undefineds(struct obj_file *f);
553
554void obj_allocate_commons(struct obj_file *f);
555
556unsigned long obj_load_size (struct obj_file *f);
557
558int obj_relocate (struct obj_file *f, ElfW(Addr) base);
559
560struct obj_file *obj_load(FILE *f);
561
562int obj_create_image (struct obj_file *f, char *image);
563
564/* Architecture specific manipulation routines. */
565
566struct obj_file *arch_new_file (void);
567
568struct obj_section *arch_new_section (void);
569
570struct obj_symbol *arch_new_symbol (void);
571
572enum obj_reloc arch_apply_relocation (struct obj_file *f,
573 struct obj_section *targsec,
574 struct obj_section *symsec,
575 struct obj_symbol *sym,
576 ElfW(RelM) *rel, ElfW(Addr) value);
577
578int arch_create_got (struct obj_file *f);
579
580struct new_module;
581int arch_init_module (struct obj_file *f, struct new_module *);
582
583#endif /* obj.h */
584//----------------------------------------------------------------------------
585//--------end of modutils obj.h
586//----------------------------------------------------------------------------
587
588
589
590
Erik Andersen02104321999-12-17 18:57:34 +0000591
Erik Andersend387d011999-12-21 02:55:11 +0000592#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000593static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000594
Eric Andersen9f16d612000-06-12 23:11:16 +0000595/*======================================================================*/
596
597int flag_force_load = 0;
598int flag_autoclean = 0;
599int flag_verbose = 0;
600int flag_export = 1;
601
602
603/*======================================================================*/
604
Eric Andersenfe4208f2000-09-24 03:44:29 +0000605/* previously, these were named i386_* but since we could be
606 compiling for the sh, I've renamed them to the more general
607 arch_* These structures are the same between the x86 and SH,
608 and we can't support anything else right now anyway. In the
609 future maybe they should be #if defined'd */
610
Eric Andersen21adca72000-12-06 18:18:26 +0000611/* Done ;-) */
612
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000613
614
615#if defined(BB_USE_PLT_ENTRIES)
616struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000617{
618 int offset;
619 int allocated:1;
620 int inited:1; /* has been set up */
621};
622#endif
623
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000624#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000625struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000626 int offset;
627 unsigned offset_done:1;
628 unsigned reloc_done:1;
629};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000630#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000631
Eric Andersen2bf658d2001-02-24 20:01:53 +0000632#if defined(__mips__)
633struct mips_hi16
634{
635 struct mips_hi16 *next;
636 Elf32_Addr *addr;
637 Elf32_Addr value;
638};
639#endif
640
Eric Andersenfe4208f2000-09-24 03:44:29 +0000641struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000642 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000643#if defined(BB_USE_PLT_ENTRIES)
644 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000645#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000646#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000647 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000648#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000649#if defined(__mips__)
650 struct mips_hi16 *mips_hi16_list;
651#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000652};
653
Eric Andersenfe4208f2000-09-24 03:44:29 +0000654struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000655 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000656#if defined(BB_USE_PLT_ENTRIES)
657 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000658#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000659#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000660 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000661#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000662};
663
664
Eric Andersen9f16d612000-06-12 23:11:16 +0000665struct external_module {
666 const char *name;
667 ElfW(Addr) addr;
668 int used;
669 size_t nsyms;
670 struct new_module_symbol *syms;
671};
672
673struct new_module_symbol *ksyms;
674size_t nksyms;
675
676struct external_module *ext_modules;
677int n_ext_modules;
678int n_ext_modules_used;
679
Erik Andersend387d011999-12-21 02:55:11 +0000680
Erik Andersen02104321999-12-17 18:57:34 +0000681extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000682
Erik Andersen02104321999-12-17 18:57:34 +0000683
Eric Andersenfe4208f2000-09-24 03:44:29 +0000684/* This is kind of troublesome. See, we don't actually support
685 the m68k or the arm the same way we support i386 and (now)
686 sh. In doing my SH patch, I just assumed that whatever works
687 for i386 also works for m68k and arm since currently insmod.c
688 does nothing special for them. If this isn't true, the below
689 line is rather misleading IMHO, and someone should either
690 change it or add more proper architecture-dependent support
691 for these boys.
692
693 -- Bryan Rittmeyer <bryan@ixiacom.com> */
694
Eric Andersen23c1a182001-03-19 19:28:24 +0000695static char m_filename[BUFSIZ + 1];
696static char m_fullName[BUFSIZ + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000697
Eric Andersen9f16d612000-06-12 23:11:16 +0000698/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000699
Eric Andersen9f16d612000-06-12 23:11:16 +0000700
701static int findNamedModule(const char *fileName, struct stat *statbuf,
702 void *userDate)
703{
704 char *fullName = (char *) userDate;
705
706
707 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000708 return (FALSE);
709 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000710 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000711
712 if (tmp == NULL)
713 tmp = (char *) fileName;
714 else
715 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000716 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000717 /* Stop searching if we find a match */
Eric Andersenf2278152001-04-24 21:41:41 +0000718 safe_strncpy(m_filename, fileName, sizeof(m_filename));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000719 return (FALSE);
720 }
Erik Andersend387d011999-12-21 02:55:11 +0000721 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000722 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000723}
724
Erik Andersen02104321999-12-17 18:57:34 +0000725
Eric Andersen9f16d612000-06-12 23:11:16 +0000726/*======================================================================*/
727
728struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000729{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000730 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000731 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000732
733#if defined(BB_USE_PLT_ENTRIES)
734 f->plt = NULL;
735#endif
736#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000737 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000738#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000739#if defined(__mips__)
740 f->mips_hi16_list = NULL;
741#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000742
Eric Andersen9f16d612000-06-12 23:11:16 +0000743 return &f->root;
744}
745
746struct obj_section *arch_new_section(void)
747{
748 return xmalloc(sizeof(struct obj_section));
749}
750
751struct obj_symbol *arch_new_symbol(void)
752{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000753 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755
756#if defined(BB_USE_PLT_ENTRIES)
757 memset(&sym->pltent, 0, sizeof(sym->pltent));
758#endif
759#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000760 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000761#endif
762
Eric Andersen9f16d612000-06-12 23:11:16 +0000763 return &sym->root;
764}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000765
Eric Andersen9f16d612000-06-12 23:11:16 +0000766enum obj_reloc
767arch_apply_relocation(struct obj_file *f,
768 struct obj_section *targsec,
769 struct obj_section *symsec,
770 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000771 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000772{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000773 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000774#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000776#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000777
Eric Andersen21adca72000-12-06 18:18:26 +0000778 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
779 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000780#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000781 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000782#endif
783#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000784 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000785 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000786 unsigned long *ip;
787#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000788 enum obj_reloc ret = obj_reloc_ok;
789
790 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000791
792/* even though these constants seem to be the same for
793 the i386 and the sh, we "#if define" them for clarity
794 and in case that ever changes */
795#if defined(__sh__)
796 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000797#elif defined(__arm__)
798 case R_ARM_NONE:
799#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000800 case R_386_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000801#elif defined(__powerpc__)
802 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000803#elif defined(__mips__)
804 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000805#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000806 break;
807
Eric Andersenfe4208f2000-09-24 03:44:29 +0000808#if defined(__sh__)
809 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000810#elif defined(__arm__)
811 case R_ARM_ABS32:
812#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000813 case R_386_32:
814#elif defined(__powerpc__)
815 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000816#elif defined(__mips__)
817 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000818#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000819 *loc += v;
820 break;
821
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000822#if defined(__powerpc__)
823 case R_PPC_ADDR16_HA:
824 *(unsigned short *)loc = (v + 0x8000) >> 16;
825 break;
826
827 case R_PPC_ADDR16_HI:
828 *(unsigned short *)loc = v >> 16;
829 break;
830
831 case R_PPC_ADDR16_LO:
832 *(unsigned short *)loc = v;
833 break;
834#endif
835
Eric Andersen2bf658d2001-02-24 20:01:53 +0000836#if defined(__mips__)
837 case R_MIPS_26:
838 if (v % 4)
839 ret = obj_reloc_dangerous;
840 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
841 ret = obj_reloc_overflow;
842 *loc =
843 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
844 0x03ffffff);
845 break;
846
847 case R_MIPS_HI16:
848 {
849 struct mips_hi16 *n;
850
851 /* We cannot relocate this one now because we don't know the value
852 of the carry we need to add. Save the information, and let LO16
853 do the actual relocation. */
854 n = (struct mips_hi16 *) xmalloc(sizeof *n);
855 n->addr = loc;
856 n->value = v;
857 n->next = ifile->mips_hi16_list;
858 ifile->mips_hi16_list = n;
859 break;
860 }
861
862 case R_MIPS_LO16:
863 {
864 unsigned long insnlo = *loc;
865 Elf32_Addr val, vallo;
866
867 /* Sign extend the addend we extract from the lo insn. */
868 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
869
870 if (ifile->mips_hi16_list != NULL) {
871 struct mips_hi16 *l;
872
873 l = ifile->mips_hi16_list;
874 while (l != NULL) {
875 struct mips_hi16 *next;
876 unsigned long insn;
877
878 /* The value for the HI16 had best be the same. */
879 assert(v == l->value);
880
881 /* Do the HI16 relocation. Note that we actually don't
882 need to know anything about the LO16 itself, except where
883 to find the low 16 bits of the addend needed by the LO16. */
884 insn = *l->addr;
885 val =
886 ((insn & 0xffff) << 16) +
887 vallo;
888 val += v;
889
890 /* Account for the sign extension that will happen in the
891 low bits. */
892 val =
893 ((val >> 16) +
894 ((val & 0x8000) !=
895 0)) & 0xffff;
896
897 insn = (insn & ~0xffff) | val;
898 *l->addr = insn;
899
900 next = l->next;
901 free(l);
902 l = next;
903 }
904
905 ifile->mips_hi16_list = NULL;
906 }
907
908 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
909 val = v + vallo;
910 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
911 *loc = insnlo;
912 break;
913 }
914#endif
915
Eric Andersen21adca72000-12-06 18:18:26 +0000916#if defined(__arm__)
917#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000918 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000919 *loc += v - dot;
920 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000921#elif defined(__i386__)
922 case R_386_PLT32:
923 case R_386_PC32:
924 *loc += v - dot;
925 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000926#elif defined(__powerpc__)
927 case R_PPC_REL32:
928 *loc = v - dot;
929 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000930#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000931
Eric Andersenfe4208f2000-09-24 03:44:29 +0000932#if defined(__sh__)
933 case R_SH_PLT32:
934 *loc = v - dot;
935 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000936#elif defined(__i386__)
937#endif
938
939#if defined(BB_USE_PLT_ENTRIES)
940
941#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000942 case R_ARM_PC24:
943 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000944#endif
945#if defined(__powerpc__)
946 case R_PPC_REL24:
947#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000948 /* find the plt entry and initialize it if necessary */
949 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000950
951 pe = (struct arch_plt_entry*) &isym->pltent;
952
Eric Andersen21adca72000-12-06 18:18:26 +0000953 if (! pe->inited) {
954 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000955
956 /* generate some machine code */
957
958#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000959 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
960 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000961#endif
962#if defined(__powerpc__)
963 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
964 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
965 ip[2] = 0x7d6903a6; /* mtctr r11 */
966 ip[3] = 0x4e800420; /* bctr */
967#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000968 pe->inited = 1;
969 }
970
971 /* relative distance to target */
972 v -= dot;
973 /* if the target is too far away.... */
974 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
975 /* go via the plt */
976 v = plt + pe->offset - dot;
977 }
978 if (v & 3)
979 ret = obj_reloc_dangerous;
980
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000981 /* merge the offset into the instruction. */
982#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000983 /* Convert to words. */
984 v >>= 2;
985
Eric Andersen21adca72000-12-06 18:18:26 +0000986 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +0000987#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000988#if defined(__powerpc__)
989 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
990#endif
991 break;
992#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +0000993
Eric Andersen21adca72000-12-06 18:18:26 +0000994#if defined(__arm__)
995#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000996 case R_SH_GLOB_DAT:
997 case R_SH_JMP_SLOT:
998 *loc = v;
999 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001000#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001001 case R_386_GLOB_DAT:
1002 case R_386_JMP_SLOT:
1003 *loc = v;
1004 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001005#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001006
Eric Andersen21adca72000-12-06 18:18:26 +00001007#if defined(__arm__)
1008#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001009 case R_SH_RELATIVE:
1010 *loc += f->baseaddr + rel->r_addend;
1011 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001012#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001013 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001014 *loc += f->baseaddr;
1015 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001016#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001017
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001018#if defined(BB_USE_GOT_ENTRIES)
1019
Eric Andersenfe4208f2000-09-24 03:44:29 +00001020#if defined(__sh__)
1021 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001022#elif defined(__arm__)
1023 case R_ARM_GOTPC:
1024#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001025 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001026#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001027 assert(got != 0);
1028#if defined(__sh__)
1029 *loc += got - dot + rel->r_addend;;
1030#elif defined(__i386__) || defined(__arm__)
1031 *loc += got - dot;
1032#endif
1033 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001034
Eric Andersenfe4208f2000-09-24 03:44:29 +00001035#if defined(__sh__)
1036 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001037#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001038 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001039#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001040 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001041#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001042 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001043 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001044 if (!isym->gotent.reloc_done) {
1045 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001046 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001047 }
Eric Andersen21adca72000-12-06 18:18:26 +00001048 /* make the reloc with_respect_to_.got */
1049#if defined(__sh__)
1050 *loc += isym->gotent.offset + rel->r_addend;
1051#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001052 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001053#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001054 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001055
Eric Andersen21adca72000-12-06 18:18:26 +00001056 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#if defined(__sh__)
1058 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001059#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001060 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001061#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001062 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001063#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001064 assert(got != 0);
1065 *loc += v - got;
1066 break;
1067
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001068#endif /* BB_USE_GOT_ENTRIES */
1069
Eric Andersen9f16d612000-06-12 23:11:16 +00001070 default:
Eric Andersen21125542000-12-13 16:41:29 +00001071 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001072 ret = obj_reloc_unhandled;
1073 break;
1074 }
1075
1076 return ret;
1077}
1078
1079int arch_create_got(struct obj_file *f)
1080{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001081#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001082 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001083 int i;
1084#if defined(BB_USE_GOT_ENTRIES)
1085 int got_offset = 0, gotneeded = 0;
1086#endif
1087#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001088 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001089#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001090 struct obj_section *relsec, *symsec, *strsec;
1091 ElfW(RelM) *rel, *relend;
1092 ElfW(Sym) *symtab, *extsym;
1093 const char *strtab, *name;
1094 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001095
Eric Andersen21adca72000-12-06 18:18:26 +00001096 for (i = 0; i < f->header.e_shnum; ++i) {
1097 relsec = f->sections[i];
1098 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001099 continue;
1100
Eric Andersen21adca72000-12-06 18:18:26 +00001101 symsec = f->sections[relsec->header.sh_link];
1102 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001103
Eric Andersen21adca72000-12-06 18:18:26 +00001104 rel = (ElfW(RelM) *) relsec->contents;
1105 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1106 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001107 strtab = (const char *) strsec->contents;
1108
1109 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001110 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001111
1112 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001113#if defined(__arm__)
1114 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001115 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001116#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001117 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001118 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001119#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001120 case R_386_GOT32:
1121 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001122#endif
1123
1124#if defined(__powerpc__)
1125 case R_PPC_REL24:
1126 pltneeded = 1;
1127 break;
1128#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001129
1130#if defined(__arm__)
1131 case R_ARM_PC24:
1132 case R_ARM_PLT32:
1133 pltneeded = 1;
1134 break;
1135
1136 case R_ARM_GOTPC:
1137 case R_ARM_GOTOFF:
1138 gotneeded = 1;
1139 if (got_offset == 0)
1140 got_offset = 4;
1141#elif defined(__sh__)
1142 case R_SH_GOTPC:
1143 case R_SH_GOTOFF:
1144 gotneeded = 1;
1145#elif defined(__i386__)
1146 case R_386_GOTPC:
1147 case R_386_GOTOFF:
1148 gotneeded = 1;
1149#endif
1150
1151 default:
1152 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001153 }
1154
Eric Andersen21adca72000-12-06 18:18:26 +00001155 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001156 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001157 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001158 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001159 }
1160 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001161#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001162 if (!intsym->gotent.offset_done) {
1163 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001164 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001165 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001166 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001167#endif
1168#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001169 if (pltneeded && intsym->pltent.allocated == 0) {
1170 intsym->pltent.allocated = 1;
1171 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001172 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001173 intsym->pltent.inited = 0;
1174 pltneeded = 0;
1175 }
1176#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001177 }
1178 }
Eric Andersen21adca72000-12-06 18:18:26 +00001179
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001180#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001181 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001182 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001183
Eric Andersene76c3b02001-04-05 03:14:39 +00001184 if (myrelsec) {
1185 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001186 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001187 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001188 BB_GOT_ENTRY_SIZE,
1189 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001190 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001191 }
1192
Eric Andersene76c3b02001-04-05 03:14:39 +00001193 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001194 }
Eric Andersen21adca72000-12-06 18:18:26 +00001195#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001196
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001197#if defined(BB_USE_PLT_ENTRIES)
1198 if (plt_offset)
1199 ifile->plt = obj_create_alloced_section(f, ".plt",
1200 BB_PLT_ENTRY_SIZE,
1201 plt_offset);
1202#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001203#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001204 return 1;
1205}
1206
1207int arch_init_module(struct obj_file *f, struct new_module *mod)
1208{
1209 return 1;
1210}
1211
1212
1213/*======================================================================*/
1214
1215/* Standard ELF hash function. */
1216inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1217{
1218 unsigned long h = 0;
1219 unsigned long g;
1220 unsigned char ch;
1221
1222 while (n > 0) {
1223 ch = *name++;
1224 h = (h << 4) + ch;
1225 if ((g = (h & 0xf0000000)) != 0) {
1226 h ^= g >> 24;
1227 h &= ~g;
1228 }
1229 n--;
1230 }
1231 return h;
1232}
1233
1234unsigned long obj_elf_hash(const char *name)
1235{
1236 return obj_elf_hash_n(name, strlen(name));
1237}
1238
1239#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1240/* Get the kernel version in the canonical integer form. */
1241
1242static int get_kernel_version(char str[STRVERSIONLEN])
1243{
1244 struct utsname uts_info;
1245 char *p, *q;
1246 int a, b, c;
1247
1248 if (uname(&uts_info) < 0)
1249 return -1;
1250 strncpy(str, uts_info.release, STRVERSIONLEN);
1251 p = uts_info.release;
1252
1253 a = strtoul(p, &p, 10);
1254 if (*p != '.')
1255 return -1;
1256 b = strtoul(p + 1, &p, 10);
1257 if (*p != '.')
1258 return -1;
1259 c = strtoul(p + 1, &q, 10);
1260 if (p + 1 == q)
1261 return -1;
1262
1263 return a << 16 | b << 8 | c;
1264}
1265
1266/* String comparison for non-co-versioned kernel and module. */
1267
1268static int ncv_strcmp(const char *a, const char *b)
1269{
1270 size_t alen = strlen(a), blen = strlen(b);
1271
1272 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1273 return strncmp(a, b, alen);
1274 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1275 return strncmp(a, b, blen);
1276 else
1277 return strcmp(a, b);
1278}
1279
1280/* String hashing for non-co-versioned kernel and module. Here
1281 we are simply forced to drop the crc from the hash. */
1282
1283static unsigned long ncv_symbol_hash(const char *str)
1284{
1285 size_t len = strlen(str);
1286 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1287 len -= 10;
1288 return obj_elf_hash_n(str, len);
1289}
1290
1291void
1292obj_set_symbol_compare(struct obj_file *f,
1293 int (*cmp) (const char *, const char *),
1294 unsigned long (*hash) (const char *))
1295{
1296 if (cmp)
1297 f->symbol_cmp = cmp;
1298 if (hash) {
1299 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1300 int i;
1301
1302 f->symbol_hash = hash;
1303
1304 memcpy(tmptab, f->symtab, sizeof(tmptab));
1305 memset(f->symtab, 0, sizeof(f->symtab));
1306
1307 for (i = 0; i < HASH_BUCKETS; ++i)
1308 for (sym = tmptab[i]; sym; sym = next) {
1309 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1310 next = sym->next;
1311 sym->next = f->symtab[h];
1312 f->symtab[h] = sym;
1313 }
1314 }
1315}
1316
1317#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1318
1319
1320struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1321 unsigned long symidx, int info,
1322 int secidx, ElfW(Addr) value,
1323 unsigned long size)
1324{
1325 struct obj_symbol *sym;
1326 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1327 int n_type = ELFW(ST_TYPE) (info);
1328 int n_binding = ELFW(ST_BIND) (info);
1329
1330 for (sym = f->symtab[hash]; sym; sym = sym->next)
1331 if (f->symbol_cmp(sym->name, name) == 0) {
1332 int o_secidx = sym->secidx;
1333 int o_info = sym->info;
1334 int o_type = ELFW(ST_TYPE) (o_info);
1335 int o_binding = ELFW(ST_BIND) (o_info);
1336
1337 /* A redefinition! Is it legal? */
1338
1339 if (secidx == SHN_UNDEF)
1340 return sym;
1341 else if (o_secidx == SHN_UNDEF)
1342 goto found;
1343 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1344 /* Cope with local and global symbols of the same name
1345 in the same object file, as might have been created
1346 by ld -r. The only reason locals are now seen at this
1347 level at all is so that we can do semi-sensible things
1348 with parameters. */
1349
1350 struct obj_symbol *nsym, **p;
1351
1352 nsym = arch_new_symbol();
1353 nsym->next = sym->next;
1354 nsym->ksymidx = -1;
1355
1356 /* Excise the old (local) symbol from the hash chain. */
1357 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1358 continue;
1359 *p = sym = nsym;
1360 goto found;
1361 } else if (n_binding == STB_LOCAL) {
1362 /* Another symbol of the same name has already been defined.
1363 Just add this to the local table. */
1364 sym = arch_new_symbol();
1365 sym->next = NULL;
1366 sym->ksymidx = -1;
1367 f->local_symtab[symidx] = sym;
1368 goto found;
1369 } else if (n_binding == STB_WEAK)
1370 return sym;
1371 else if (o_binding == STB_WEAK)
1372 goto found;
1373 /* Don't unify COMMON symbols with object types the programmer
1374 doesn't expect. */
1375 else if (secidx == SHN_COMMON
1376 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1377 return sym;
1378 else if (o_secidx == SHN_COMMON
1379 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1380 goto found;
1381 else {
1382 /* Don't report an error if the symbol is coming from
1383 the kernel or some external module. */
1384 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001385 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001386 return sym;
1387 }
1388 }
1389
1390 /* Completely new symbol. */
1391 sym = arch_new_symbol();
1392 sym->next = f->symtab[hash];
1393 f->symtab[hash] = sym;
1394 sym->ksymidx = -1;
1395
1396 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1397 f->local_symtab[symidx] = sym;
1398
1399 found:
1400 sym->name = name;
1401 sym->value = value;
1402 sym->size = size;
1403 sym->secidx = secidx;
1404 sym->info = info;
1405
1406 return sym;
1407}
1408
1409struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1410{
1411 struct obj_symbol *sym;
1412 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1413
1414 for (sym = f->symtab[hash]; sym; sym = sym->next)
1415 if (f->symbol_cmp(sym->name, name) == 0)
1416 return sym;
1417
1418 return NULL;
1419}
1420
1421ElfW(Addr)
1422 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1423{
1424 if (sym) {
1425 if (sym->secidx >= SHN_LORESERVE)
1426 return sym->value;
1427
1428 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1429 } else {
1430 /* As a special case, a NULL sym has value zero. */
1431 return 0;
1432 }
1433}
1434
1435struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1436{
1437 int i, n = f->header.e_shnum;
1438
1439 for (i = 0; i < n; ++i)
1440 if (strcmp(f->sections[i]->name, name) == 0)
1441 return f->sections[i];
1442
1443 return NULL;
1444}
1445
1446static int obj_load_order_prio(struct obj_section *a)
1447{
1448 unsigned long af, ac;
1449
1450 af = a->header.sh_flags;
1451
1452 ac = 0;
1453 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1454 strcmp(a->name + 5, ".init"))
1455 ac |= 32;
1456 if (af & SHF_ALLOC)
1457 ac |= 16;
1458 if (!(af & SHF_WRITE))
1459 ac |= 8;
1460 if (af & SHF_EXECINSTR)
1461 ac |= 4;
1462 if (a->header.sh_type != SHT_NOBITS)
1463 ac |= 2;
1464
1465 return ac;
1466}
1467
1468void
1469obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1470{
1471 struct obj_section **p;
1472 int prio = obj_load_order_prio(sec);
1473 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1474 if (obj_load_order_prio(*p) < prio)
1475 break;
1476 sec->load_next = *p;
1477 *p = sec;
1478}
1479
1480struct obj_section *obj_create_alloced_section(struct obj_file *f,
1481 const char *name,
1482 unsigned long align,
1483 unsigned long size)
1484{
1485 int newidx = f->header.e_shnum++;
1486 struct obj_section *sec;
1487
1488 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1489 f->sections[newidx] = sec = arch_new_section();
1490
1491 memset(sec, 0, sizeof(*sec));
1492 sec->header.sh_type = SHT_PROGBITS;
1493 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1494 sec->header.sh_size = size;
1495 sec->header.sh_addralign = align;
1496 sec->name = name;
1497 sec->idx = newidx;
1498 if (size)
1499 sec->contents = xmalloc(size);
1500
1501 obj_insert_section_load_order(f, sec);
1502
1503 return sec;
1504}
1505
1506struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1507 const char *name,
1508 unsigned long align,
1509 unsigned long size)
1510{
1511 int newidx = f->header.e_shnum++;
1512 struct obj_section *sec;
1513
1514 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1515 f->sections[newidx] = sec = arch_new_section();
1516
1517 memset(sec, 0, sizeof(*sec));
1518 sec->header.sh_type = SHT_PROGBITS;
1519 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1520 sec->header.sh_size = size;
1521 sec->header.sh_addralign = align;
1522 sec->name = name;
1523 sec->idx = newidx;
1524 if (size)
1525 sec->contents = xmalloc(size);
1526
1527 sec->load_next = f->load_order;
1528 f->load_order = sec;
1529 if (f->load_order_search_start == &f->load_order)
1530 f->load_order_search_start = &sec->load_next;
1531
1532 return sec;
1533}
1534
1535void *obj_extend_section(struct obj_section *sec, unsigned long more)
1536{
1537 unsigned long oldsize = sec->header.sh_size;
1538 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1539 return sec->contents + oldsize;
1540}
1541
1542
1543
1544/* Conditionally add the symbols from the given symbol set to the
1545 new module. */
1546
1547static int
1548add_symbols_from(
1549 struct obj_file *f,
1550 int idx, struct new_module_symbol *syms, size_t nsyms)
1551{
1552 struct new_module_symbol *s;
1553 size_t i;
1554 int used = 0;
1555
1556 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1557
1558 /* Only add symbols that are already marked external. If we
1559 override locals we may cause problems for argument initialization.
1560 We will also create a false dependency on the module. */
1561 struct obj_symbol *sym;
1562
1563 sym = obj_find_symbol(f, (char *) s->name);
1564 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1565 sym = obj_add_symbol(f, (char *) s->name, -1,
1566 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1567 idx, s->value, 0);
1568 /* Did our symbol just get installed? If so, mark the
1569 module as "used". */
1570 if (sym->secidx == idx)
1571 used = 1;
1572 }
1573 }
1574
1575 return used;
1576}
1577
1578static void add_kernel_symbols(struct obj_file *f)
1579{
1580 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001581 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001582
1583 /* Add module symbols first. */
1584
1585 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1586 if (m->nsyms
1587 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1588 m->nsyms)) m->used = 1, ++nused;
1589
1590 n_ext_modules_used = nused;
1591
1592 /* And finally the symbols from the kernel proper. */
1593
1594 if (nksyms)
1595 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1596}
1597
1598static char *get_modinfo_value(struct obj_file *f, const char *key)
1599{
1600 struct obj_section *sec;
1601 char *p, *v, *n, *ep;
1602 size_t klen = strlen(key);
1603
1604 sec = obj_find_section(f, ".modinfo");
1605 if (sec == NULL)
1606 return NULL;
1607 p = sec->contents;
1608 ep = p + sec->header.sh_size;
1609 while (p < ep) {
1610 v = strchr(p, '=');
1611 n = strchr(p, '\0');
1612 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001613 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001614 return v + 1;
1615 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001616 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001617 return n;
1618 }
1619 p = n + 1;
1620 }
1621
1622 return NULL;
1623}
1624
1625
1626/*======================================================================*/
1627/* Functions relating to module loading in pre 2.1 kernels. */
1628
1629static int
1630old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1631{
1632 while (argc > 0) {
1633 char *p, *q;
1634 struct obj_symbol *sym;
1635 int *loc;
1636
1637 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001638 if ((q = strchr(p, '=')) == NULL) {
1639 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001640 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001641 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001642 *q++ = '\0';
1643
1644 sym = obj_find_symbol(f, p);
1645
1646 /* Also check that the parameter was not resolved from the kernel. */
1647 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001648 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001649 return 0;
1650 }
1651
1652 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1653
1654 /* Do C quoting if we begin with a ". */
1655 if (*q == '"') {
1656 char *r, *str;
1657
1658 str = alloca(strlen(q));
1659 for (r = str, q++; *q != '"'; ++q, ++r) {
1660 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001661 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001662 return 0;
1663 } else if (*q == '\\')
1664 switch (*++q) {
1665 case 'a':
1666 *r = '\a';
1667 break;
1668 case 'b':
1669 *r = '\b';
1670 break;
1671 case 'e':
1672 *r = '\033';
1673 break;
1674 case 'f':
1675 *r = '\f';
1676 break;
1677 case 'n':
1678 *r = '\n';
1679 break;
1680 case 'r':
1681 *r = '\r';
1682 break;
1683 case 't':
1684 *r = '\t';
1685 break;
1686
1687 case '0':
1688 case '1':
1689 case '2':
1690 case '3':
1691 case '4':
1692 case '5':
1693 case '6':
1694 case '7':
1695 {
1696 int c = *q - '0';
1697 if (q[1] >= '0' && q[1] <= '7') {
1698 c = (c * 8) + *++q - '0';
1699 if (q[1] >= '0' && q[1] <= '7')
1700 c = (c * 8) + *++q - '0';
1701 }
1702 *r = c;
1703 }
1704 break;
1705
1706 default:
1707 *r = *q;
1708 break;
1709 } else
1710 *r = *q;
1711 }
1712 *r = '\0';
1713 obj_string_patch(f, sym->secidx, sym->value, str);
1714 } else if (*q >= '0' && *q <= '9') {
1715 do
1716 *loc++ = strtoul(q, &q, 0);
1717 while (*q++ == ',');
1718 } else {
1719 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001720 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001721 char *r; /* To search for commas */
1722
1723 /* Break the string with comas */
1724 while ((r = strchr(q, ',')) != (char *) NULL) {
1725 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001726 obj_string_patch(f, sym->secidx, myloc - contents, q);
1727 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001728 q = r;
1729 }
1730
1731 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001732 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001733 }
1734
1735 argc--, argv++;
1736 }
1737
1738 return 1;
1739}
1740
1741#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1742static int old_is_module_checksummed(struct obj_file *f)
1743{
1744 return obj_find_symbol(f, "Using_Versions") != NULL;
1745}
1746/* Get the module's kernel version in the canonical integer form. */
1747
1748static int
1749old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1750{
1751 struct obj_symbol *sym;
1752 char *p, *q;
1753 int a, b, c;
1754
1755 sym = obj_find_symbol(f, "kernel_version");
1756 if (sym == NULL)
1757 return -1;
1758
1759 p = f->sections[sym->secidx]->contents + sym->value;
1760 strncpy(str, p, STRVERSIONLEN);
1761
1762 a = strtoul(p, &p, 10);
1763 if (*p != '.')
1764 return -1;
1765 b = strtoul(p + 1, &p, 10);
1766 if (*p != '.')
1767 return -1;
1768 c = strtoul(p + 1, &q, 10);
1769 if (p + 1 == q)
1770 return -1;
1771
1772 return a << 16 | b << 8 | c;
1773}
1774
1775#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1776
Eric Andersenf5d5e772001-01-24 23:34:48 +00001777#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001778
1779/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1780
Eric Andersen8c185f92000-09-22 00:38:07 +00001781static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001782{
1783 struct old_kernel_sym *ks, *k;
1784 struct new_module_symbol *s;
1785 struct external_module *mod;
1786 int nks, nms, nmod, i;
1787
1788 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001789 if (nks <= 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001790 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001791 return 0;
1792 }
1793
1794 ks = k = xmalloc(nks * sizeof(*ks));
1795
1796 if (get_kernel_syms(ks) != nks) {
1797 perror("inconsistency with get_kernel_syms -- is someone else "
1798 "playing with modules?");
1799 free(ks);
1800 return 0;
1801 }
1802
1803 /* Collect the module information. */
1804
1805 mod = NULL;
1806 nmod = -1;
1807
1808 while (k->name[0] == '#' && k->name[1]) {
1809 struct old_kernel_sym *k2;
1810 struct new_module_symbol *s;
1811
1812 /* Find out how many symbols this module has. */
1813 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1814 continue;
1815 nms = k2 - k - 1;
1816
1817 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1818 mod[nmod].name = k->name + 1;
1819 mod[nmod].addr = k->value;
1820 mod[nmod].used = 0;
1821 mod[nmod].nsyms = nms;
1822 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1823
1824 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1825 s->name = (unsigned long) k->name;
1826 s->value = k->value;
1827 }
1828
1829 k = k2;
1830 }
1831
1832 ext_modules = mod;
1833 n_ext_modules = nmod + 1;
1834
1835 /* Now collect the symbols for the kernel proper. */
1836
1837 if (k->name[0] == '#')
1838 ++k;
1839
1840 nksyms = nms = nks - (k - ks);
1841 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1842
1843 for (i = 0; i < nms; ++i, ++s, ++k) {
1844 s->name = (unsigned long) k->name;
1845 s->value = k->value;
1846 }
1847
1848 return 1;
1849}
1850
1851/* Return the kernel symbol checksum version, or zero if not used. */
1852
1853static int old_is_kernel_checksummed(void)
1854{
1855 /* Using_Versions is the first symbol. */
1856 if (nksyms > 0
1857 && strcmp((char *) ksyms[0].name,
1858 "Using_Versions") == 0) return ksyms[0].value;
1859 else
1860 return 0;
1861}
1862
1863
1864static int old_create_mod_use_count(struct obj_file *f)
1865{
1866 struct obj_section *sec;
1867
1868 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1869 sizeof(long));
1870
1871 obj_add_symbol(f, "mod_use_count_", -1,
1872 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1873 sizeof(long));
1874
1875 return 1;
1876}
1877
1878static int
1879old_init_module(const char *m_name, struct obj_file *f,
1880 unsigned long m_size)
1881{
1882 char *image;
1883 struct old_mod_routines routines;
1884 struct old_symbol_table *symtab;
1885 int ret;
1886
1887 /* Create the symbol table */
1888 {
1889 int nsyms = 0, strsize = 0, total;
1890
1891 /* Size things first... */
1892 if (flag_export) {
1893 int i;
1894 for (i = 0; i < HASH_BUCKETS; ++i) {
1895 struct obj_symbol *sym;
1896 for (sym = f->symtab[i]; sym; sym = sym->next)
1897 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1898 && sym->secidx <= SHN_HIRESERVE)
1899 {
1900 sym->ksymidx = nsyms++;
1901 strsize += strlen(sym->name) + 1;
1902 }
1903 }
1904 }
1905
1906 total = (sizeof(struct old_symbol_table)
1907 + nsyms * sizeof(struct old_module_symbol)
1908 + n_ext_modules_used * sizeof(struct old_module_ref)
1909 + strsize);
1910 symtab = xmalloc(total);
1911 symtab->size = total;
1912 symtab->n_symbols = nsyms;
1913 symtab->n_refs = n_ext_modules_used;
1914
1915 if (flag_export && nsyms) {
1916 struct old_module_symbol *ksym;
1917 char *str;
1918 int i;
1919
1920 ksym = symtab->symbol;
1921 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1922 + n_ext_modules_used * sizeof(struct old_module_ref));
1923
1924 for (i = 0; i < HASH_BUCKETS; ++i) {
1925 struct obj_symbol *sym;
1926 for (sym = f->symtab[i]; sym; sym = sym->next)
1927 if (sym->ksymidx >= 0) {
1928 ksym->addr = obj_symbol_final_value(f, sym);
1929 ksym->name =
1930 (unsigned long) str - (unsigned long) symtab;
1931
Matt Kraai70a78552001-01-04 02:00:17 +00001932 strcpy(str, sym->name);
1933 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001934 ksym++;
1935 }
1936 }
1937 }
1938
1939 if (n_ext_modules_used) {
1940 struct old_module_ref *ref;
1941 int i;
1942
1943 ref = (struct old_module_ref *)
1944 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1945
1946 for (i = 0; i < n_ext_modules; ++i)
1947 if (ext_modules[i].used)
1948 ref++->module = ext_modules[i].addr;
1949 }
1950 }
1951
1952 /* Fill in routines. */
1953
1954 routines.init =
1955 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1956 routines.cleanup =
1957 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1958
1959 /* Whew! All of the initialization is complete. Collect the final
1960 module image and give it to the kernel. */
1961
1962 image = xmalloc(m_size);
1963 obj_create_image(f, image);
1964
1965 /* image holds the complete relocated module, accounting correctly for
1966 mod_use_count. However the old module kernel support assume that
1967 it is receiving something which does not contain mod_use_count. */
1968 ret = old_sys_init_module(m_name, image + sizeof(long),
1969 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1970 : 0), &routines, symtab);
1971 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001972 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001973
1974 free(image);
1975 free(symtab);
1976
1977 return ret == 0;
1978}
1979
1980#else
1981
1982#define old_create_mod_use_count(x) TRUE
1983#define old_init_module(x, y, z) TRUE
1984
Eric Andersenf5d5e772001-01-24 23:34:48 +00001985#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00001986
1987
1988
1989/*======================================================================*/
1990/* Functions relating to module loading after 2.1.18. */
1991
1992static int
1993new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1994{
1995 while (argc > 0) {
1996 char *p, *q, *key;
1997 struct obj_symbol *sym;
1998 char *contents, *loc;
1999 int min, max, n;
2000
2001 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002002 if ((q = strchr(p, '=')) == NULL) {
2003 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002004 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002005 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002006
2007 key = alloca(q - p + 6);
2008 memcpy(key, "parm_", 5);
2009 memcpy(key + 5, p, q - p);
2010 key[q - p + 5] = 0;
2011
2012 p = get_modinfo_value(f, key);
2013 key += 5;
2014 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002015 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002016 return 0;
2017 }
2018
2019 sym = obj_find_symbol(f, key);
2020
2021 /* Also check that the parameter was not resolved from the kernel. */
2022 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002023 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002024 return 0;
2025 }
2026
2027 if (isdigit(*p)) {
2028 min = strtoul(p, &p, 10);
2029 if (*p == '-')
2030 max = strtoul(p + 1, &p, 10);
2031 else
2032 max = min;
2033 } else
2034 min = max = 1;
2035
2036 contents = f->sections[sym->secidx]->contents;
2037 loc = contents + sym->value;
2038 n = (*++q != '\0');
2039
2040 while (1) {
2041 if ((*p == 's') || (*p == 'c')) {
2042 char *str;
2043
2044 /* Do C quoting if we begin with a ", else slurp the lot. */
2045 if (*q == '"') {
2046 char *r;
2047
2048 str = alloca(strlen(q));
2049 for (r = str, q++; *q != '"'; ++q, ++r) {
2050 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002051 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002052 key);
2053 return 0;
2054 } else if (*q == '\\')
2055 switch (*++q) {
2056 case 'a':
2057 *r = '\a';
2058 break;
2059 case 'b':
2060 *r = '\b';
2061 break;
2062 case 'e':
2063 *r = '\033';
2064 break;
2065 case 'f':
2066 *r = '\f';
2067 break;
2068 case 'n':
2069 *r = '\n';
2070 break;
2071 case 'r':
2072 *r = '\r';
2073 break;
2074 case 't':
2075 *r = '\t';
2076 break;
2077
2078 case '0':
2079 case '1':
2080 case '2':
2081 case '3':
2082 case '4':
2083 case '5':
2084 case '6':
2085 case '7':
2086 {
2087 int c = *q - '0';
2088 if (q[1] >= '0' && q[1] <= '7') {
2089 c = (c * 8) + *++q - '0';
2090 if (q[1] >= '0' && q[1] <= '7')
2091 c = (c * 8) + *++q - '0';
2092 }
2093 *r = c;
2094 }
2095 break;
2096
2097 default:
2098 *r = *q;
2099 break;
2100 } else
2101 *r = *q;
2102 }
2103 *r = '\0';
2104 ++q;
2105 } else {
2106 char *r;
2107
2108 /* In this case, the string is not quoted. We will break
2109 it using the coma (like for ints). If the user wants to
2110 include comas in a string, he just has to quote it */
2111
2112 /* Search the next coma */
2113 r = strchr(q, ',');
2114
2115 /* Found ? */
2116 if (r != (char *) NULL) {
2117 /* Recopy the current field */
2118 str = alloca(r - q + 1);
2119 memcpy(str, q, r - q);
2120
2121 /* I don't know if it is usefull, as the previous case
2122 doesn't null terminate the string ??? */
2123 str[r - q] = '\0';
2124
2125 /* Keep next fields */
2126 q = r;
2127 } else {
2128 /* last string */
2129 str = q;
2130 q = "";
2131 }
2132 }
2133
2134 if (*p == 's') {
2135 /* Normal string */
2136 obj_string_patch(f, sym->secidx, loc - contents, str);
2137 loc += tgt_sizeof_char_p;
2138 } else {
2139 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002140 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002141
2142 /* Get the size of each member */
2143 /* Probably we should do that outside the loop ? */
2144 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002145 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002146 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002147 return 0;
2148 }
2149 charssize = strtoul(p + 1, (char **) NULL, 10);
2150
2151 /* Check length */
2152 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002153 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002154 charssize - 1);
2155 return 0;
2156 }
2157
2158 /* Copy to location */
2159 strcpy((char *) loc, str);
2160 loc += charssize;
2161 }
2162 } else {
2163 long v = strtoul(q, &q, 0);
2164 switch (*p) {
2165 case 'b':
2166 *loc++ = v;
2167 break;
2168 case 'h':
2169 *(short *) loc = v;
2170 loc += tgt_sizeof_short;
2171 break;
2172 case 'i':
2173 *(int *) loc = v;
2174 loc += tgt_sizeof_int;
2175 break;
2176 case 'l':
2177 *(long *) loc = v;
2178 loc += tgt_sizeof_long;
2179 break;
2180
2181 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002182 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002183 return 0;
2184 }
2185 }
2186
2187 retry_end_of_value:
2188 switch (*q) {
2189 case '\0':
2190 goto end_of_arg;
2191
2192 case ' ':
2193 case '\t':
2194 case '\n':
2195 case '\r':
2196 ++q;
2197 goto retry_end_of_value;
2198
2199 case ',':
2200 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002201 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002202 return 0;
2203 }
2204 ++q;
2205 break;
2206
2207 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002208 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002209 return 0;
2210 }
2211 }
2212
2213 end_of_arg:
2214 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002215 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002216 return 0;
2217 }
2218
2219 argc--, argv++;
2220 }
2221
2222 return 1;
2223}
2224
2225#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2226static int new_is_module_checksummed(struct obj_file *f)
2227{
2228 const char *p = get_modinfo_value(f, "using_checksums");
2229 if (p)
2230 return atoi(p);
2231 else
2232 return 0;
2233}
2234
2235/* Get the module's kernel version in the canonical integer form. */
2236
2237static int
2238new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2239{
2240 char *p, *q;
2241 int a, b, c;
2242
2243 p = get_modinfo_value(f, "kernel_version");
2244 if (p == NULL)
2245 return -1;
2246 strncpy(str, p, STRVERSIONLEN);
2247
2248 a = strtoul(p, &p, 10);
2249 if (*p != '.')
2250 return -1;
2251 b = strtoul(p + 1, &p, 10);
2252 if (*p != '.')
2253 return -1;
2254 c = strtoul(p + 1, &q, 10);
2255 if (p + 1 == q)
2256 return -1;
2257
2258 return a << 16 | b << 8 | c;
2259}
2260
2261#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2262
2263
Eric Andersenf5d5e772001-01-24 23:34:48 +00002264#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002265
2266/* Fetch the loaded modules, and all currently exported symbols. */
2267
2268static int new_get_kernel_symbols(void)
2269{
2270 char *module_names, *mn;
2271 struct external_module *modules, *m;
2272 struct new_module_symbol *syms, *s;
2273 size_t ret, bufsize, nmod, nsyms, i, j;
2274
2275 /* Collect the loaded modules. */
2276
2277 module_names = xmalloc(bufsize = 256);
2278 retry_modules_load:
2279 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2280 if (errno == ENOSPC) {
2281 module_names = xrealloc(module_names, bufsize = ret);
2282 goto retry_modules_load;
2283 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002284 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002285 return 0;
2286 }
2287
2288 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002289
2290 /* Collect the modules' symbols. */
2291
Mark Whitley94fd4802001-03-12 23:08:34 +00002292 if (nmod){
2293 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2294 memset(modules, 0, nmod * sizeof(*modules));
2295 for (i = 0, mn = module_names, m = modules;
2296 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2297 struct new_module_info info;
2298
2299 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2300 if (errno == ENOENT) {
2301 /* The module was removed out from underneath us. */
2302 continue;
2303 }
2304 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002305 return 0;
2306 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002307
2308 syms = xmalloc(bufsize = 1024);
2309 retry_mod_sym_load:
2310 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2311 switch (errno) {
2312 case ENOSPC:
2313 syms = xrealloc(syms, bufsize = ret);
2314 goto retry_mod_sym_load;
2315 case ENOENT:
2316 /* The module was removed out from underneath us. */
2317 continue;
2318 default:
2319 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2320 return 0;
2321 }
2322 }
2323 nsyms = ret;
2324
2325 m->name = mn;
2326 m->addr = info.addr;
2327 m->nsyms = nsyms;
2328 m->syms = syms;
2329
2330 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2331 s->name += (unsigned long) syms;
2332 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002333 }
2334 }
2335
2336 /* Collect the kernel's symbols. */
2337
2338 syms = xmalloc(bufsize = 16 * 1024);
2339 retry_kern_sym_load:
2340 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2341 if (errno == ENOSPC) {
2342 syms = xrealloc(syms, bufsize = ret);
2343 goto retry_kern_sym_load;
2344 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002345 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002346 return 0;
2347 }
2348 nksyms = nsyms = ret;
2349 ksyms = syms;
2350
2351 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2352 s->name += (unsigned long) syms;
2353 }
2354 return 1;
2355}
2356
2357
2358/* Return the kernel symbol checksum version, or zero if not used. */
2359
2360static int new_is_kernel_checksummed(void)
2361{
2362 struct new_module_symbol *s;
2363 size_t i;
2364
2365 /* Using_Versions is not the first symbol, but it should be in there. */
2366
2367 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2368 if (strcmp((char *) s->name, "Using_Versions") == 0)
2369 return s->value;
2370
2371 return 0;
2372}
2373
2374
2375static int new_create_this_module(struct obj_file *f, const char *m_name)
2376{
2377 struct obj_section *sec;
2378
2379 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2380 sizeof(struct new_module));
2381 memset(sec->contents, 0, sizeof(struct new_module));
2382
2383 obj_add_symbol(f, "__this_module", -1,
2384 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2385 sizeof(struct new_module));
2386
2387 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2388 m_name);
2389
2390 return 1;
2391}
2392
2393
2394static int new_create_module_ksymtab(struct obj_file *f)
2395{
2396 struct obj_section *sec;
2397 int i;
2398
2399 /* We must always add the module references. */
2400
2401 if (n_ext_modules_used) {
2402 struct new_module_ref *dep;
2403 struct obj_symbol *tm;
2404
2405 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2406 (sizeof(struct new_module_ref)
2407 * n_ext_modules_used));
2408 if (!sec)
2409 return 0;
2410
2411 tm = obj_find_symbol(f, "__this_module");
2412 dep = (struct new_module_ref *) sec->contents;
2413 for (i = 0; i < n_ext_modules; ++i)
2414 if (ext_modules[i].used) {
2415 dep->dep = ext_modules[i].addr;
2416 obj_symbol_patch(f, sec->idx,
2417 (char *) &dep->ref - sec->contents, tm);
2418 dep->next_ref = 0;
2419 ++dep;
2420 }
2421 }
2422
2423 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2424 size_t nsyms;
2425 int *loaded;
2426
2427 sec =
2428 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2429 0);
2430
2431 /* We don't want to export symbols residing in sections that
2432 aren't loaded. There are a number of these created so that
2433 we make sure certain module options don't appear twice. */
2434
2435 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2436 while (--i >= 0)
2437 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2438
2439 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2440 struct obj_symbol *sym;
2441 for (sym = f->symtab[i]; sym; sym = sym->next)
2442 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2443 && sym->secidx <= SHN_HIRESERVE
2444 && (sym->secidx >= SHN_LORESERVE
2445 || loaded[sym->secidx])) {
2446 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2447
2448 obj_symbol_patch(f, sec->idx, ofs, sym);
2449 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2450 sym->name);
2451
2452 nsyms++;
2453 }
2454 }
2455
2456 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2457 }
2458
2459 return 1;
2460}
2461
2462
2463static int
2464new_init_module(const char *m_name, struct obj_file *f,
2465 unsigned long m_size)
2466{
2467 struct new_module *module;
2468 struct obj_section *sec;
2469 void *image;
2470 int ret;
2471 tgt_long m_addr;
2472
2473 sec = obj_find_section(f, ".this");
2474 module = (struct new_module *) sec->contents;
2475 m_addr = sec->header.sh_addr;
2476
2477 module->size_of_struct = sizeof(*module);
2478 module->size = m_size;
2479 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2480
2481 sec = obj_find_section(f, "__ksymtab");
2482 if (sec && sec->header.sh_size) {
2483 module->syms = sec->header.sh_addr;
2484 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2485 }
2486
2487 if (n_ext_modules_used) {
2488 sec = obj_find_section(f, ".kmodtab");
2489 module->deps = sec->header.sh_addr;
2490 module->ndeps = n_ext_modules_used;
2491 }
2492
2493 module->init =
2494 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2495 module->cleanup =
2496 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2497
2498 sec = obj_find_section(f, "__ex_table");
2499 if (sec) {
2500 module->ex_table_start = sec->header.sh_addr;
2501 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2502 }
2503
2504 sec = obj_find_section(f, ".text.init");
2505 if (sec) {
2506 module->runsize = sec->header.sh_addr - m_addr;
2507 }
2508 sec = obj_find_section(f, ".data.init");
2509 if (sec) {
2510 if (!module->runsize ||
2511 module->runsize > sec->header.sh_addr - m_addr)
2512 module->runsize = sec->header.sh_addr - m_addr;
2513 }
2514
2515 if (!arch_init_module(f, module))
2516 return 0;
2517
2518 /* Whew! All of the initialization is complete. Collect the final
2519 module image and give it to the kernel. */
2520
2521 image = xmalloc(m_size);
2522 obj_create_image(f, image);
2523
Eric Andersen64c8b172001-04-05 07:33:10 +00002524 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002525 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002526 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002527
2528 free(image);
2529
2530 return ret == 0;
2531}
2532
2533#else
2534
2535#define new_init_module(x, y, z) TRUE
2536#define new_create_this_module(x, y) 0
2537#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002538#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002539
Eric Andersenf5d5e772001-01-24 23:34:48 +00002540#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002541
2542
2543/*======================================================================*/
2544
2545int
2546obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2547 const char *string)
2548{
2549 struct obj_string_patch *p;
2550 struct obj_section *strsec;
2551 size_t len = strlen(string) + 1;
2552 char *loc;
2553
2554 p = xmalloc(sizeof(*p));
2555 p->next = f->string_patches;
2556 p->reloc_secidx = secidx;
2557 p->reloc_offset = offset;
2558 f->string_patches = p;
2559
2560 strsec = obj_find_section(f, ".kstrtab");
2561 if (strsec == NULL) {
2562 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2563 p->string_offset = 0;
2564 loc = strsec->contents;
2565 } else {
2566 p->string_offset = strsec->header.sh_size;
2567 loc = obj_extend_section(strsec, len);
2568 }
2569 memcpy(loc, string, len);
2570
2571 return 1;
2572}
2573
2574int
2575obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2576 struct obj_symbol *sym)
2577{
2578 struct obj_symbol_patch *p;
2579
2580 p = xmalloc(sizeof(*p));
2581 p->next = f->symbol_patches;
2582 p->reloc_secidx = secidx;
2583 p->reloc_offset = offset;
2584 p->sym = sym;
2585 f->symbol_patches = p;
2586
2587 return 1;
2588}
2589
2590int obj_check_undefineds(struct obj_file *f)
2591{
2592 unsigned long i;
2593 int ret = 1;
2594
2595 for (i = 0; i < HASH_BUCKETS; ++i) {
2596 struct obj_symbol *sym;
2597 for (sym = f->symtab[i]; sym; sym = sym->next)
2598 if (sym->secidx == SHN_UNDEF) {
2599 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2600 sym->secidx = SHN_ABS;
2601 sym->value = 0;
2602 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002603 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002604 ret = 0;
2605 }
2606 }
2607 }
2608
2609 return ret;
2610}
2611
2612void obj_allocate_commons(struct obj_file *f)
2613{
2614 struct common_entry {
2615 struct common_entry *next;
2616 struct obj_symbol *sym;
2617 } *common_head = NULL;
2618
2619 unsigned long i;
2620
2621 for (i = 0; i < HASH_BUCKETS; ++i) {
2622 struct obj_symbol *sym;
2623 for (sym = f->symtab[i]; sym; sym = sym->next)
2624 if (sym->secidx == SHN_COMMON) {
2625 /* Collect all COMMON symbols and sort them by size so as to
2626 minimize space wasted by alignment requirements. */
2627 {
2628 struct common_entry **p, *n;
2629 for (p = &common_head; *p; p = &(*p)->next)
2630 if (sym->size <= (*p)->sym->size)
2631 break;
2632
2633 n = alloca(sizeof(*n));
2634 n->next = *p;
2635 n->sym = sym;
2636 *p = n;
2637 }
2638 }
2639 }
2640
2641 for (i = 1; i < f->local_symtab_size; ++i) {
2642 struct obj_symbol *sym = f->local_symtab[i];
2643 if (sym && sym->secidx == SHN_COMMON) {
2644 struct common_entry **p, *n;
2645 for (p = &common_head; *p; p = &(*p)->next)
2646 if (sym == (*p)->sym)
2647 break;
2648 else if (sym->size < (*p)->sym->size) {
2649 n = alloca(sizeof(*n));
2650 n->next = *p;
2651 n->sym = sym;
2652 *p = n;
2653 break;
2654 }
2655 }
2656 }
2657
2658 if (common_head) {
2659 /* Find the bss section. */
2660 for (i = 0; i < f->header.e_shnum; ++i)
2661 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2662 break;
2663
2664 /* If for some reason there hadn't been one, create one. */
2665 if (i == f->header.e_shnum) {
2666 struct obj_section *sec;
2667
2668 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2669 f->sections[i] = sec = arch_new_section();
2670 f->header.e_shnum = i + 1;
2671
2672 memset(sec, 0, sizeof(*sec));
2673 sec->header.sh_type = SHT_PROGBITS;
2674 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2675 sec->name = ".bss";
2676 sec->idx = i;
2677 }
2678
2679 /* Allocate the COMMONS. */
2680 {
2681 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2682 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2683 struct common_entry *c;
2684
2685 for (c = common_head; c; c = c->next) {
2686 ElfW(Addr) align = c->sym->value;
2687
2688 if (align > max_align)
2689 max_align = align;
2690 if (bss_size & (align - 1))
2691 bss_size = (bss_size | (align - 1)) + 1;
2692
2693 c->sym->secidx = i;
2694 c->sym->value = bss_size;
2695
2696 bss_size += c->sym->size;
2697 }
2698
2699 f->sections[i]->header.sh_size = bss_size;
2700 f->sections[i]->header.sh_addralign = max_align;
2701 }
2702 }
2703
2704 /* For the sake of patch relocation and parameter initialization,
2705 allocate zeroed data for NOBITS sections now. Note that after
2706 this we cannot assume NOBITS are really empty. */
2707 for (i = 0; i < f->header.e_shnum; ++i) {
2708 struct obj_section *s = f->sections[i];
2709 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002710 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002711 s->contents = memset(xmalloc(s->header.sh_size),
2712 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002713 else
2714 s->contents = NULL;
2715
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 s->header.sh_type = SHT_PROGBITS;
2717 }
2718 }
2719}
2720
2721unsigned long obj_load_size(struct obj_file *f)
2722{
2723 unsigned long dot = 0;
2724 struct obj_section *sec;
2725
2726 /* Finalize the positions of the sections relative to one another. */
2727
2728 for (sec = f->load_order; sec; sec = sec->load_next) {
2729 ElfW(Addr) align;
2730
2731 align = sec->header.sh_addralign;
2732 if (align && (dot & (align - 1)))
2733 dot = (dot | (align - 1)) + 1;
2734
2735 sec->header.sh_addr = dot;
2736 dot += sec->header.sh_size;
2737 }
2738
2739 return dot;
2740}
2741
2742int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2743{
2744 int i, n = f->header.e_shnum;
2745 int ret = 1;
2746
2747 /* Finalize the addresses of the sections. */
2748
2749 f->baseaddr = base;
2750 for (i = 0; i < n; ++i)
2751 f->sections[i]->header.sh_addr += base;
2752
2753 /* And iterate over all of the relocations. */
2754
2755 for (i = 0; i < n; ++i) {
2756 struct obj_section *relsec, *symsec, *targsec, *strsec;
2757 ElfW(RelM) * rel, *relend;
2758 ElfW(Sym) * symtab;
2759 const char *strtab;
2760
2761 relsec = f->sections[i];
2762 if (relsec->header.sh_type != SHT_RELM)
2763 continue;
2764
2765 symsec = f->sections[relsec->header.sh_link];
2766 targsec = f->sections[relsec->header.sh_info];
2767 strsec = f->sections[symsec->header.sh_link];
2768
2769 rel = (ElfW(RelM) *) relsec->contents;
2770 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2771 symtab = (ElfW(Sym) *) symsec->contents;
2772 strtab = (const char *) strsec->contents;
2773
2774 for (; rel < relend; ++rel) {
2775 ElfW(Addr) value = 0;
2776 struct obj_symbol *intsym = NULL;
2777 unsigned long symndx;
2778 ElfW(Sym) * extsym = 0;
2779 const char *errmsg;
2780
2781 /* Attempt to find a value to use for this relocation. */
2782
2783 symndx = ELFW(R_SYM) (rel->r_info);
2784 if (symndx) {
2785 /* Note we've already checked for undefined symbols. */
2786
2787 extsym = &symtab[symndx];
2788 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2789 /* Local symbols we look up in the local table to be sure
2790 we get the one that is really intended. */
2791 intsym = f->local_symtab[symndx];
2792 } else {
2793 /* Others we look up in the hash table. */
2794 const char *name;
2795 if (extsym->st_name)
2796 name = strtab + extsym->st_name;
2797 else
2798 name = f->sections[extsym->st_shndx]->name;
2799 intsym = obj_find_symbol(f, name);
2800 }
2801
2802 value = obj_symbol_final_value(f, intsym);
2803 intsym->referenced = 1;
2804 }
2805#if SHT_RELM == SHT_RELA
2806#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2807 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2808 if (!extsym || !extsym->st_name ||
2809 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2810#endif
2811 value += rel->r_addend;
2812#endif
2813
2814 /* Do it! */
2815 switch (arch_apply_relocation
2816 (f, targsec, symsec, intsym, rel, value)) {
2817 case obj_reloc_ok:
2818 break;
2819
2820 case obj_reloc_overflow:
2821 errmsg = "Relocation overflow";
2822 goto bad_reloc;
2823 case obj_reloc_dangerous:
2824 errmsg = "Dangerous relocation";
2825 goto bad_reloc;
2826 case obj_reloc_unhandled:
2827 errmsg = "Unhandled relocation";
2828 bad_reloc:
2829 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002830 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002831 (long) ELFW(R_TYPE) (rel->r_info),
2832 strtab + extsym->st_name);
2833 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002834 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002835 (long) ELFW(R_TYPE) (rel->r_info));
2836 }
2837 ret = 0;
2838 break;
2839 }
2840 }
2841 }
2842
2843 /* Finally, take care of the patches. */
2844
2845 if (f->string_patches) {
2846 struct obj_string_patch *p;
2847 struct obj_section *strsec;
2848 ElfW(Addr) strsec_base;
2849 strsec = obj_find_section(f, ".kstrtab");
2850 strsec_base = strsec->header.sh_addr;
2851
2852 for (p = f->string_patches; p; p = p->next) {
2853 struct obj_section *targsec = f->sections[p->reloc_secidx];
2854 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2855 = strsec_base + p->string_offset;
2856 }
2857 }
2858
2859 if (f->symbol_patches) {
2860 struct obj_symbol_patch *p;
2861
2862 for (p = f->symbol_patches; p; p = p->next) {
2863 struct obj_section *targsec = f->sections[p->reloc_secidx];
2864 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2865 = obj_symbol_final_value(f, p->sym);
2866 }
2867 }
2868
2869 return ret;
2870}
2871
2872int obj_create_image(struct obj_file *f, char *image)
2873{
2874 struct obj_section *sec;
2875 ElfW(Addr) base = f->baseaddr;
2876
2877 for (sec = f->load_order; sec; sec = sec->load_next) {
2878 char *secimg;
2879
Eric Andersen2bf658d2001-02-24 20:01:53 +00002880 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002881 continue;
2882
2883 secimg = image + (sec->header.sh_addr - base);
2884
2885 /* Note that we allocated data for NOBITS sections earlier. */
2886 memcpy(secimg, sec->contents, sec->header.sh_size);
2887 }
2888
2889 return 1;
2890}
2891
2892/*======================================================================*/
2893
2894struct obj_file *obj_load(FILE * fp)
2895{
2896 struct obj_file *f;
2897 ElfW(Shdr) * section_headers;
2898 int shnum, i;
2899 char *shstrtab;
2900
2901 /* Read the file header. */
2902
2903 f = arch_new_file();
2904 memset(f, 0, sizeof(*f));
2905 f->symbol_cmp = strcmp;
2906 f->symbol_hash = obj_elf_hash;
2907 f->load_order_search_start = &f->load_order;
2908
2909 fseek(fp, 0, SEEK_SET);
2910 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002911 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002912 return NULL;
2913 }
2914
2915 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2916 || f->header.e_ident[EI_MAG1] != ELFMAG1
2917 || f->header.e_ident[EI_MAG2] != ELFMAG2
2918 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002919 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002920 return NULL;
2921 }
2922 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2923 || f->header.e_ident[EI_DATA] != ELFDATAM
2924 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2925 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002926 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002927 return NULL;
2928 }
2929 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002930 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002931 return NULL;
2932 }
2933
2934 /* Read the section headers. */
2935
2936 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002937 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00002938 (unsigned long) f->header.e_shentsize,
2939 (unsigned long) sizeof(ElfW(Shdr)));
2940 return NULL;
2941 }
2942
2943 shnum = f->header.e_shnum;
2944 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2945 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2946
2947 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2948 fseek(fp, f->header.e_shoff, SEEK_SET);
2949 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002950 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002951 return NULL;
2952 }
2953
2954 /* Read the section data. */
2955
2956 for (i = 0; i < shnum; ++i) {
2957 struct obj_section *sec;
2958
2959 f->sections[i] = sec = arch_new_section();
2960 memset(sec, 0, sizeof(*sec));
2961
2962 sec->header = section_headers[i];
2963 sec->idx = i;
2964
Eric Andersen2bf658d2001-02-24 20:01:53 +00002965 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002966 case SHT_NULL:
2967 case SHT_NOTE:
2968 case SHT_NOBITS:
2969 /* ignore */
2970 break;
2971
2972 case SHT_PROGBITS:
2973 case SHT_SYMTAB:
2974 case SHT_STRTAB:
2975 case SHT_RELM:
2976 if (sec->header.sh_size > 0) {
2977 sec->contents = xmalloc(sec->header.sh_size);
2978 fseek(fp, sec->header.sh_offset, SEEK_SET);
2979 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002980 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002981 return NULL;
2982 }
2983 } else {
2984 sec->contents = NULL;
2985 }
2986 break;
2987
2988#if SHT_RELM == SHT_REL
2989 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00002990 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002991 return NULL;
2992#else
2993 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00002994 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002995 return NULL;
2996#endif
2997
2998 default:
2999 if (sec->header.sh_type >= SHT_LOPROC) {
3000 /* Assume processor specific section types are debug
3001 info and can safely be ignored. If this is ever not
3002 the case (Hello MIPS?), don't put ifdefs here but
3003 create an arch_load_proc_section(). */
3004 break;
3005 }
3006
Matt Kraaidd19c692001-01-31 19:00:21 +00003007 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003008 (long) sec->header.sh_type);
3009 return NULL;
3010 }
3011 }
3012
3013 /* Do what sort of interpretation as needed by each section. */
3014
3015 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3016
3017 for (i = 0; i < shnum; ++i) {
3018 struct obj_section *sec = f->sections[i];
3019 sec->name = shstrtab + sec->header.sh_name;
3020 }
3021
3022 for (i = 0; i < shnum; ++i) {
3023 struct obj_section *sec = f->sections[i];
3024
3025 if (sec->header.sh_flags & SHF_ALLOC)
3026 obj_insert_section_load_order(f, sec);
3027
3028 switch (sec->header.sh_type) {
3029 case SHT_SYMTAB:
3030 {
3031 unsigned long nsym, j;
3032 char *strtab;
3033 ElfW(Sym) * sym;
3034
3035 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003036 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003037 (unsigned long) sec->header.sh_entsize,
3038 (unsigned long) sizeof(ElfW(Sym)));
3039 return NULL;
3040 }
3041
3042 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3043 strtab = f->sections[sec->header.sh_link]->contents;
3044 sym = (ElfW(Sym) *) sec->contents;
3045
3046 /* Allocate space for a table of local symbols. */
3047 j = f->local_symtab_size = sec->header.sh_info;
3048 f->local_symtab = xmalloc(j *=
3049 sizeof(struct obj_symbol *));
3050 memset(f->local_symtab, 0, j);
3051
3052 /* Insert all symbols into the hash table. */
3053 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3054 const char *name;
3055 if (sym->st_name)
3056 name = strtab + sym->st_name;
3057 else
3058 name = f->sections[sym->st_shndx]->name;
3059
3060 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3061 sym->st_value, sym->st_size);
3062 }
3063 }
3064 break;
3065
3066 case SHT_RELM:
3067 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003068 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003069 (unsigned long) sec->header.sh_entsize,
3070 (unsigned long) sizeof(ElfW(RelM)));
3071 return NULL;
3072 }
3073 break;
3074 }
3075 }
3076
3077 return f;
3078}
3079
3080static void hide_special_symbols(struct obj_file *f)
3081{
3082 static const char *const specials[] = {
3083 "cleanup_module",
3084 "init_module",
3085 "kernel_version",
3086 NULL
3087 };
3088
3089 struct obj_symbol *sym;
3090 const char *const *p;
3091
3092 for (p = specials; *p; ++p)
3093 if ((sym = obj_find_symbol(f, *p)) != NULL)
3094 sym->info =
3095 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3096}
3097
3098
3099
3100extern int insmod_main( int argc, char **argv)
3101{
Eric Andersena18aaf12001-01-24 19:07:09 +00003102 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003103 int k_crcs;
3104 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003105 int len;
3106 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003107 unsigned long m_size;
3108 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003109 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003110 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003111 struct stat st;
Eric Andersen9f16d612000-06-12 23:11:16 +00003112 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003113 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003114 int m_has_modinfo;
3115#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3116 int k_version;
3117 char k_strversion[STRVERSIONLEN];
3118 char m_strversion[STRVERSIONLEN];
3119 int m_version;
3120 int m_crcs;
3121#endif
3122
Erik Andersene49d5ec2000-02-08 19:58:47 +00003123 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003124 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003125 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003126 case 'f': /* force loading */
3127 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003128 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003129 case 'k': /* module loaded by kerneld, auto-cleanable */
3130 flag_autoclean = 1;
3131 break;
3132 case 'v': /* verbose output */
3133 flag_verbose = 1;
3134 break;
3135 case 'x': /* do not export externs */
3136 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003137 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003138 case 'o': /* name the output module */
3139 strncpy(m_name, optarg, BUFSIZ);
3140 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003141 case 'L': /* Stub warning */
3142 /* This is needed for compatibility with modprobe.
3143 * In theory, this does locking, but we don't do
3144 * that. So be careful and plan your life around not
3145 * loading the same module 50 times concurrently. */
3146 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003147 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003148 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003149 }
Erik Andersend387d011999-12-21 02:55:11 +00003150 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003151
3152 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003153 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003154 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003155
Erik Andersene49d5ec2000-02-08 19:58:47 +00003156 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003157 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003158 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003159 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003160 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003161 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003162 len = strlen(tmp);
3163
3164 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3165 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003166 memcpy(m_fullName, tmp, len);
3167 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003168 if (*m_name == '\0') {
3169 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003170 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003171 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003172
3173 /* Get a filedesc for the module */
Eric Andersen02b9f422001-02-15 19:07:43 +00003174 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3175 (fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003176 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00003177 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003178 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003179 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003180 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00003181 || ((fp = fopen(m_filename, "r")) == NULL))
3182 {
Matt Kraaidd19c692001-01-31 19:00:21 +00003183 error_msg("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00003184 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003185 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003186 } else
Matt Kraaidd19c692001-01-31 19:00:21 +00003187 error_msg_and_die("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003188 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003189 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003190
3191
Matt Kraaia9819b22000-12-22 01:48:07 +00003192 if ((f = obj_load(fp)) == NULL)
3193 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003194
Eric Andersen9f16d612000-06-12 23:11:16 +00003195 if (get_modinfo_value(f, "kernel_version") == NULL)
3196 m_has_modinfo = 0;
3197 else
3198 m_has_modinfo = 1;
3199
3200#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3201 /* Version correspondence? */
3202
3203 k_version = get_kernel_version(k_strversion);
3204 if (m_has_modinfo) {
3205 m_version = new_get_module_version(f, m_strversion);
3206 } else {
3207 m_version = old_get_module_version(f, m_strversion);
3208 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003209 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003210 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003211 goto out;
3212 }
3213 }
3214
3215 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3216 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003217 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003218 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003219 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003220 m_filename, m_strversion, k_strversion);
3221 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003222 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003223 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003224 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003225 m_filename, m_strversion, k_strversion);
3226 goto out;
3227 }
3228 }
3229 k_crcs = 0;
3230#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3231
3232 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3233
3234 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003235#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003236 if (!new_get_kernel_symbols())
3237 goto out;
3238 k_crcs = new_is_kernel_checksummed();
3239#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003240 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003241 goto out;
3242#endif
3243 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003244#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003245 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003246 goto out;
3247 k_crcs = old_is_kernel_checksummed();
3248#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003249 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 goto out;
3251#endif
3252 }
3253
3254#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3255 if (m_has_modinfo)
3256 m_crcs = new_is_module_checksummed(f);
3257 else
3258 m_crcs = old_is_module_checksummed(f);
3259
3260 if (m_crcs != k_crcs)
3261 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3262#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3263
Erik Andersene49d5ec2000-02-08 19:58:47 +00003264 /* Let the module know about the kernel symbols. */
3265 add_kernel_symbols(f);
3266
Eric Andersen9f16d612000-06-12 23:11:16 +00003267 /* Allocate common symbols, symbol tables, and string tables. */
3268
3269 if (k_new_syscalls
3270 ? !new_create_this_module(f, m_name)
3271 : !old_create_mod_use_count(f))
3272 {
3273 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003274 }
3275
Eric Andersen9f16d612000-06-12 23:11:16 +00003276 if (!obj_check_undefineds(f)) {
3277 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003278 }
3279 obj_allocate_commons(f);
3280
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003281 /* done with the module name, on to the optional var=value arguments */
3282 ++optind;
3283
Eric Andersen9f16d612000-06-12 23:11:16 +00003284 if (optind < argc) {
3285 if (m_has_modinfo
3286 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3287 : !old_process_module_arguments(f, argc - optind, argv + optind))
3288 {
3289 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003290 }
3291 }
3292
Eric Andersen9f16d612000-06-12 23:11:16 +00003293 arch_create_got(f);
3294 hide_special_symbols(f);
3295
3296 if (k_new_syscalls)
3297 new_create_module_ksymtab(f);
3298
Erik Andersene49d5ec2000-02-08 19:58:47 +00003299 /* Find current size of the module */
3300 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003301
3302
Erik Andersene49d5ec2000-02-08 19:58:47 +00003303 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003304 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003305 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003306 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003307 goto out;
3308 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003309 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003310 m_size);
3311 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003312 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003313 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003314 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003315 }
Erik Andersend387d011999-12-21 02:55:11 +00003316
Eric Andersen9f16d612000-06-12 23:11:16 +00003317 if (!obj_relocate(f, m_addr)) {
3318 delete_module(m_name);
3319 goto out;
3320 }
Erik Andersend387d011999-12-21 02:55:11 +00003321
Eric Andersen9f16d612000-06-12 23:11:16 +00003322 if (k_new_syscalls
3323 ? !new_init_module(m_name, f, m_size)
3324 : !old_init_module(m_name, f, m_size))
3325 {
3326 delete_module(m_name);
3327 goto out;
3328 }
3329
Matt Kraai3e856ce2000-12-01 02:55:13 +00003330 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003331
3332out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003333 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003334 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003335}