blob: 0a7cb1e4ab3156fd43d177fbca75a3b176e9e173 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
4 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00005 * Copyright (C) 1999,2000,2001 by Lineo, inc.
Eric Andersen9f16d612000-06-12 23:11:16 +00006 * Written by Erik Andersen <andersen@lineo.com>
7 * and Ron Alder <alder@lineo.com>
8 *
Eric Andersenfe4208f2000-09-24 03:44:29 +00009 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000010 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
11 *
12 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
13 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
14 * very minor changes required to also work with StrongArm and presumably
15 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000017 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
18 * PowerPC specific code stolen from modutils-2.3.16,
19 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
20 * I've only tested the code on mpc8xx platforms in big-endian mode.
21 * Did some cleanup and added BB_USE_xxx_ENTRIES...
22 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000023 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
24 * based on modutils-2.4.2
25 * MIPS specific support for Elf loading and relocation.
26 * Copyright 1996, 1997 Linux International.
27 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
28 *
Eric Andersen9f16d612000-06-12 23:11:16 +000029 * Based almost entirely on the Linux modutils-2.3.11 implementation.
30 * Copyright 1996, 1997 Linux International.
31 * New implementation contributed by Richard Henderson <rth@tamu.edu>
32 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
33 * Restructured (and partly rewritten) by:
34 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000035 *
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation; either version 2 of the License, or
39 * (at your option) any later version.
40 *
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software
48 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
49 *
50 */
51
Erik Andersen02104321999-12-17 18:57:34 +000052#include <stdlib.h>
53#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000054#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000055#include <errno.h>
56#include <unistd.h>
57#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000058#include <ctype.h>
59#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000060#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000061#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000062#include <sys/utsname.h>
Eric Andersened3ef502001-01-27 08:24:39 +000063#include <sys/syscall.h>
64#include <linux/unistd.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000065#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000066
Eric Andersen90fe7fe2001-02-20 20:47:08 +000067#if defined(__powerpc__)
68#define BB_USE_PLT_ENTRIES
69#define BB_PLT_ENTRY_SIZE 16
70#endif
71
72#if defined(__arm__)
73#define BB_USE_PLT_ENTRIES
74#define BB_PLT_ENTRY_SIZE 8
75#define BB_USE_GOT_ENTRIES
76#define BB_GOT_ENTRY_SIZE 8
77#endif
78
79#if defined(__sh__)
80#define BB_USE_GOT_ENTRIES
81#define BB_GOT_ENTRY_SIZE 4
82#endif
83
84#if defined(__i386__)
85#define BB_USE_GOT_ENTRIES
86#define BB_GOT_ENTRY_SIZE 4
87#endif
88
Eric Andersen2bf658d2001-02-24 20:01:53 +000089#if defined(__mips__)
90// neither used
91#endif
92
Eric Andersen9f16d612000-06-12 23:11:16 +000093//----------------------------------------------------------------------------
94//--------modutils module.h, lines 45-242
95//----------------------------------------------------------------------------
96
97/* Definitions for the Linux module syscall interface.
98 Copyright 1996, 1997 Linux International.
99
100 Contributed by Richard Henderson <rth@tamu.edu>
101
102 This file is part of the Linux modutils.
103
104 This program is free software; you can redistribute it and/or modify it
105 under the terms of the GNU General Public License as published by the
106 Free Software Foundation; either version 2 of the License, or (at your
107 option) any later version.
108
109 This program is distributed in the hope that it will be useful, but
110 WITHOUT ANY WARRANTY; without even the implied warranty of
111 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
112 General Public License for more details.
113
114 You should have received a copy of the GNU General Public License
115 along with this program; if not, write to the Free Software Foundation,
116 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
117
118
119#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000120static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000121
Eric Andersen82bb8a22001-03-22 19:01:16 +0000122#ident "$Id: insmod.c,v 1.53 2001/03/22 19:01:16 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000123
124/* This file contains the structures used by the 2.0 and 2.1 kernels.
125 We do not use the kernel headers directly because we do not wish
126 to be dependant on a particular kernel version to compile insmod. */
127
128
129/*======================================================================*/
130/* The structures used by Linux 2.0. */
131
132/* The symbol format used by get_kernel_syms(2). */
133struct old_kernel_sym
134{
135 unsigned long value;
136 char name[60];
137};
138
139struct old_module_ref
140{
141 unsigned long module; /* kernel addresses */
142 unsigned long next;
143};
144
145struct old_module_symbol
146{
147 unsigned long addr;
148 unsigned long name;
149};
150
151struct old_symbol_table
152{
153 int size; /* total, including string table!!! */
154 int n_symbols;
155 int n_refs;
156 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
157 struct old_module_ref ref[0]; /* actual size defined by n_refs */
158};
159
160struct old_mod_routines
161{
162 unsigned long init;
163 unsigned long cleanup;
164};
165
166struct old_module
167{
168 unsigned long next;
169 unsigned long ref; /* the list of modules that refer to me */
170 unsigned long symtab;
171 unsigned long name;
172 int size; /* size of module in pages */
173 unsigned long addr; /* address of module */
174 int state;
175 unsigned long cleanup; /* cleanup routine */
176};
177
178/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000179static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000180
181int get_kernel_syms(struct old_kernel_sym *);
182int old_sys_init_module(const char *name, char *code, unsigned codesize,
183 struct old_mod_routines *, struct old_symbol_table *);
184
185/*======================================================================*/
186/* For sizeof() which are related to the module platform and not to the
187 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
188
189#define tgt_sizeof_char sizeof(char)
190#define tgt_sizeof_short sizeof(short)
191#define tgt_sizeof_int sizeof(int)
192#define tgt_sizeof_long sizeof(long)
193#define tgt_sizeof_char_p sizeof(char *)
194#define tgt_sizeof_void_p sizeof(void *)
195#define tgt_long long
196
197#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
198#undef tgt_sizeof_long
199#undef tgt_sizeof_char_p
200#undef tgt_sizeof_void_p
201#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000202static const int tgt_sizeof_long = 8;
203static const int tgt_sizeof_char_p = 8;
204static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000205#define tgt_long long long
206#endif
207
208/*======================================================================*/
209/* The structures used in Linux 2.1. */
210
211/* Note: new_module_symbol does not use tgt_long intentionally */
212struct new_module_symbol
213{
214 unsigned long value;
215 unsigned long name;
216};
217
218struct new_module_persist;
219
220struct new_module_ref
221{
222 unsigned tgt_long dep; /* kernel addresses */
223 unsigned tgt_long ref;
224 unsigned tgt_long next_ref;
225};
226
227struct new_module
228{
229 unsigned tgt_long size_of_struct; /* == sizeof(module) */
230 unsigned tgt_long next;
231 unsigned tgt_long name;
232 unsigned tgt_long size;
233
234 tgt_long usecount;
235 unsigned tgt_long flags; /* AUTOCLEAN et al */
236
237 unsigned nsyms;
238 unsigned ndeps;
239
240 unsigned tgt_long syms;
241 unsigned tgt_long deps;
242 unsigned tgt_long refs;
243 unsigned tgt_long init;
244 unsigned tgt_long cleanup;
245 unsigned tgt_long ex_table_start;
246 unsigned tgt_long ex_table_end;
247#ifdef __alpha__
248 unsigned tgt_long gp;
249#endif
250 /* Everything after here is extension. */
251 unsigned tgt_long persist_start;
252 unsigned tgt_long persist_end;
253 unsigned tgt_long can_unload;
254 unsigned tgt_long runsize;
255};
256
257struct new_module_info
258{
259 unsigned long addr;
260 unsigned long size;
261 unsigned long flags;
262 long usecount;
263};
264
265/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000266static const int NEW_MOD_RUNNING = 1;
267static const int NEW_MOD_DELETED = 2;
268static const int NEW_MOD_AUTOCLEAN = 4;
269static const int NEW_MOD_VISITED = 8;
270static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000271
272int new_sys_init_module(const char *name, const struct new_module *);
273int query_module(const char *name, int which, void *buf, size_t bufsize,
274 size_t *ret);
275
276/* Values for query_module's which. */
277
Mark Whitley59ab0252001-01-23 22:30:04 +0000278static const int QM_MODULES = 1;
279static const int QM_DEPS = 2;
280static const int QM_REFS = 3;
281static const int QM_SYMBOLS = 4;
282static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000283
284/*======================================================================*/
285/* The system calls unchanged between 2.0 and 2.1. */
286
287unsigned long create_module(const char *, size_t);
288int delete_module(const char *);
289
290
291#endif /* module.h */
292
293//----------------------------------------------------------------------------
294//--------end of modutils module.h
295//----------------------------------------------------------------------------
296
297
298
299//----------------------------------------------------------------------------
300//--------modutils obj.h, lines 253-462
301//----------------------------------------------------------------------------
302
303/* Elf object file loading and relocation routines.
304 Copyright 1996, 1997 Linux International.
305
306 Contributed by Richard Henderson <rth@tamu.edu>
307
308 This file is part of the Linux modutils.
309
310 This program is free software; you can redistribute it and/or modify it
311 under the terms of the GNU General Public License as published by the
312 Free Software Foundation; either version 2 of the License, or (at your
313 option) any later version.
314
315 This program is distributed in the hope that it will be useful, but
316 WITHOUT ANY WARRANTY; without even the implied warranty of
317 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
318 General Public License for more details.
319
320 You should have received a copy of the GNU General Public License
321 along with this program; if not, write to the Free Software Foundation,
322 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
323
324
325#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000326static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000327
Eric Andersen82bb8a22001-03-22 19:01:16 +0000328#ident "$Id: insmod.c,v 1.53 2001/03/22 19:01:16 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000329
330/* The relocatable object is manipulated using elfin types. */
331
332#include <stdio.h>
333#include <elf.h>
334
335
336/* Machine-specific elf macros for i386 et al. */
337
Eric Andersenfe4208f2000-09-24 03:44:29 +0000338/* the SH changes have only been tested on the SH4 in =little endian= mode */
339/* I'm not sure about big endian, so let's warn: */
340
341#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
342#error insmod.c may require changes for use on big endian SH4/SH3
343#endif
344
345/* it may or may not work on the SH1/SH2... So let's error on those
346 also */
347#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
348#error insmod.c may require changes for non-SH3/SH4 use
349#endif
350
Eric Andersen9f16d612000-06-12 23:11:16 +0000351#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000352
353#if defined(__sh__)
354
355#define MATCH_MACHINE(x) (x == EM_SH)
356#define SHT_RELM SHT_RELA
357#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000358#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000359
Eric Andersen21adca72000-12-06 18:18:26 +0000360#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000361
Eric Andersen21adca72000-12-06 18:18:26 +0000362#define MATCH_MACHINE(x) (x == EM_ARM)
363#define SHT_RELM SHT_REL
364#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000365#define ELFDATAM ELFDATA2LSB
366
367#elif defined(__powerpc__)
368
369#define MATCH_MACHINE(x) (x == EM_PPC)
370#define SHT_RELM SHT_RELA
371#define Elf32_RelM Elf32_Rela
372#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000373
Eric Andersen2bf658d2001-02-24 20:01:53 +0000374#elif defined(__mips__)
375
Eric Andersen82bb8a22001-03-22 19:01:16 +0000376/* Account for ELF spec changes. */
377#ifndef EM_MIPS_RS3_LE
378#ifdef EM_MIPS_RS4_BE
379#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
380#else
381#define EM_MIPS_RS3_LE 10
382#endif
383#endif /* !EM_MIPS_RS3_LE */
384
Eric Andersen2bf658d2001-02-24 20:01:53 +0000385#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
386#define SHT_RELM SHT_REL
387#define Elf32_RelM Elf32_Rel
388#ifdef __MIPSEB__
389#define ELFDATAM ELFDATA2MSB
390#endif
391#ifdef __MIPSEL__
392#define ELFDATAM ELFDATA2LSB
393#endif
394
Eric Andersen21adca72000-12-06 18:18:26 +0000395#elif defined(__i386__)
396
397/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000398/* this is the previous behavior, but it does result in
399 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000400#ifndef EM_486
401#define MATCH_MACHINE(x) (x == EM_386)
402#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000403#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000404#endif
405
Eric Andersen9f16d612000-06-12 23:11:16 +0000406#define SHT_RELM SHT_REL
407#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000408#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000409
Eric Andersen21adca72000-12-06 18:18:26 +0000410#else
Eric Andersend5cad142001-01-26 02:23:57 +0000411#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000412#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000413
414#ifndef ElfW
415# if ELFCLASSM == ELFCLASS32
416# define ElfW(x) Elf32_ ## x
417# define ELFW(x) ELF32_ ## x
418# else
419# define ElfW(x) Elf64_ ## x
420# define ELFW(x) ELF64_ ## x
421# endif
422#endif
423
424/* For some reason this is missing from libc5. */
425#ifndef ELF32_ST_INFO
426# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
427#endif
428
429#ifndef ELF64_ST_INFO
430# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
431#endif
432
433struct obj_string_patch;
434struct obj_symbol_patch;
435
436struct obj_section
437{
438 ElfW(Shdr) header;
439 const char *name;
440 char *contents;
441 struct obj_section *load_next;
442 int idx;
443};
444
445struct obj_symbol
446{
447 struct obj_symbol *next; /* hash table link */
448 const char *name;
449 unsigned long value;
450 unsigned long size;
451 int secidx; /* the defining section index/module */
452 int info;
453 int ksymidx; /* for export to the kernel symtab */
454 int referenced; /* actually used in the link */
455};
456
457/* Hardcode the hash table size. We shouldn't be needing so many
458 symbols that we begin to degrade performance, and we get a big win
459 by giving the compiler a constant divisor. */
460
461#define HASH_BUCKETS 521
462
463struct obj_file
464{
465 ElfW(Ehdr) header;
466 ElfW(Addr) baseaddr;
467 struct obj_section **sections;
468 struct obj_section *load_order;
469 struct obj_section **load_order_search_start;
470 struct obj_string_patch *string_patches;
471 struct obj_symbol_patch *symbol_patches;
472 int (*symbol_cmp)(const char *, const char *);
473 unsigned long (*symbol_hash)(const char *);
474 unsigned long local_symtab_size;
475 struct obj_symbol **local_symtab;
476 struct obj_symbol *symtab[HASH_BUCKETS];
477};
478
479enum obj_reloc
480{
481 obj_reloc_ok,
482 obj_reloc_overflow,
483 obj_reloc_dangerous,
484 obj_reloc_unhandled
485};
486
487struct obj_string_patch
488{
489 struct obj_string_patch *next;
490 int reloc_secidx;
491 ElfW(Addr) reloc_offset;
492 ElfW(Addr) string_offset;
493};
494
495struct obj_symbol_patch
496{
497 struct obj_symbol_patch *next;
498 int reloc_secidx;
499 ElfW(Addr) reloc_offset;
500 struct obj_symbol *sym;
501};
502
503
504/* Generic object manipulation routines. */
505
506unsigned long obj_elf_hash(const char *);
507
508unsigned long obj_elf_hash_n(const char *, unsigned long len);
509
510struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
511 unsigned long symidx, int info, int secidx,
512 ElfW(Addr) value, unsigned long size);
513
514struct obj_symbol *obj_find_symbol (struct obj_file *f,
515 const char *name);
516
517ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
518 struct obj_symbol *sym);
519
520void obj_set_symbol_compare(struct obj_file *f,
521 int (*cmp)(const char *, const char *),
522 unsigned long (*hash)(const char *));
523
524struct obj_section *obj_find_section (struct obj_file *f,
525 const char *name);
526
527void obj_insert_section_load_order (struct obj_file *f,
528 struct obj_section *sec);
529
530struct obj_section *obj_create_alloced_section (struct obj_file *f,
531 const char *name,
532 unsigned long align,
533 unsigned long size);
534
535struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
536 const char *name,
537 unsigned long align,
538 unsigned long size);
539
540void *obj_extend_section (struct obj_section *sec, unsigned long more);
541
542int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
543 const char *string);
544
545int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
546 struct obj_symbol *sym);
547
548int obj_check_undefineds(struct obj_file *f);
549
550void obj_allocate_commons(struct obj_file *f);
551
552unsigned long obj_load_size (struct obj_file *f);
553
554int obj_relocate (struct obj_file *f, ElfW(Addr) base);
555
556struct obj_file *obj_load(FILE *f);
557
558int obj_create_image (struct obj_file *f, char *image);
559
560/* Architecture specific manipulation routines. */
561
562struct obj_file *arch_new_file (void);
563
564struct obj_section *arch_new_section (void);
565
566struct obj_symbol *arch_new_symbol (void);
567
568enum obj_reloc arch_apply_relocation (struct obj_file *f,
569 struct obj_section *targsec,
570 struct obj_section *symsec,
571 struct obj_symbol *sym,
572 ElfW(RelM) *rel, ElfW(Addr) value);
573
574int arch_create_got (struct obj_file *f);
575
576struct new_module;
577int arch_init_module (struct obj_file *f, struct new_module *);
578
579#endif /* obj.h */
580//----------------------------------------------------------------------------
581//--------end of modutils obj.h
582//----------------------------------------------------------------------------
583
584
585
586
Erik Andersen02104321999-12-17 18:57:34 +0000587
Erik Andersend387d011999-12-21 02:55:11 +0000588#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000589static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000590
Eric Andersen9f16d612000-06-12 23:11:16 +0000591/*======================================================================*/
592
593int flag_force_load = 0;
594int flag_autoclean = 0;
595int flag_verbose = 0;
596int flag_export = 1;
597
598
599/*======================================================================*/
600
Eric Andersenfe4208f2000-09-24 03:44:29 +0000601/* previously, these were named i386_* but since we could be
602 compiling for the sh, I've renamed them to the more general
603 arch_* These structures are the same between the x86 and SH,
604 and we can't support anything else right now anyway. In the
605 future maybe they should be #if defined'd */
606
Eric Andersen21adca72000-12-06 18:18:26 +0000607/* Done ;-) */
608
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000609
610
611#if defined(BB_USE_PLT_ENTRIES)
612struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000613{
614 int offset;
615 int allocated:1;
616 int inited:1; /* has been set up */
617};
618#endif
619
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000620#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000621struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000622 int offset;
623 unsigned offset_done:1;
624 unsigned reloc_done:1;
625};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000626#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000627
Eric Andersen2bf658d2001-02-24 20:01:53 +0000628#if defined(__mips__)
629struct mips_hi16
630{
631 struct mips_hi16 *next;
632 Elf32_Addr *addr;
633 Elf32_Addr value;
634};
635#endif
636
Eric Andersenfe4208f2000-09-24 03:44:29 +0000637struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000638 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000639#if defined(BB_USE_PLT_ENTRIES)
640 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000641#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000642#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000643 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000644#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000645#if defined(__mips__)
646 struct mips_hi16 *mips_hi16_list;
647#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000648};
649
Eric Andersenfe4208f2000-09-24 03:44:29 +0000650struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000651 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000652#if defined(BB_USE_PLT_ENTRIES)
653 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000654#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000655#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000656 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000657#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000658};
659
660
Eric Andersen9f16d612000-06-12 23:11:16 +0000661struct external_module {
662 const char *name;
663 ElfW(Addr) addr;
664 int used;
665 size_t nsyms;
666 struct new_module_symbol *syms;
667};
668
669struct new_module_symbol *ksyms;
670size_t nksyms;
671
672struct external_module *ext_modules;
673int n_ext_modules;
674int n_ext_modules_used;
675
Erik Andersend387d011999-12-21 02:55:11 +0000676
677
Erik Andersen02104321999-12-17 18:57:34 +0000678/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000679#define __NR_new_sys_init_module __NR_init_module
680_syscall2(int, new_sys_init_module, const char *, name,
681 const struct new_module *, info)
682#define __NR_old_sys_init_module __NR_init_module
683_syscall5(int, old_sys_init_module, const char *, name, char *, code,
684 unsigned, codesize, struct old_mod_routines *, routines,
685 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000686#ifndef BB_RMMOD
687_syscall1(int, delete_module, const char *, name)
688#else
689extern int delete_module(const char *);
690#endif
691
Eric Andersenfe4208f2000-09-24 03:44:29 +0000692/* This is kind of troublesome. See, we don't actually support
693 the m68k or the arm the same way we support i386 and (now)
694 sh. In doing my SH patch, I just assumed that whatever works
695 for i386 also works for m68k and arm since currently insmod.c
696 does nothing special for them. If this isn't true, the below
697 line is rather misleading IMHO, and someone should either
698 change it or add more proper architecture-dependent support
699 for these boys.
700
701 -- Bryan Rittmeyer <bryan@ixiacom.com> */
702
Eric Andersenf5d5e772001-01-24 23:34:48 +0000703#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen21adca72000-12-06 18:18:26 +0000704_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
705#endif
706
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000707#if defined(__i386__) || defined(__m68k__) || defined(__arm__) \
708 || defined(__powerpc__)
Erik Andersen02104321999-12-17 18:57:34 +0000709/* Jump through hoops to fixup error return codes */
710#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000711static inline _syscall2(long, _create_module, const char *, name, size_t,
712 size)
Erik Andersen02104321999-12-17 18:57:34 +0000713unsigned long create_module(const char *name, size_t size)
714{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000715 long ret = _create_module(name, size);
716
717 if (ret == -1 && errno > 125) {
718 ret = -errno;
719 errno = 0;
720 }
721 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000722}
723#else
724_syscall2(unsigned long, create_module, const char *, name, size_t, size)
725#endif
Eric Andersen23c1a182001-03-19 19:28:24 +0000726static char m_filename[BUFSIZ + 1];
727static char m_fullName[BUFSIZ + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000728
Eric Andersen9f16d612000-06-12 23:11:16 +0000729/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000730
Eric Andersen9f16d612000-06-12 23:11:16 +0000731
732static int findNamedModule(const char *fileName, struct stat *statbuf,
733 void *userDate)
734{
735 char *fullName = (char *) userDate;
736
737
738 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000739 return (FALSE);
740 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000741 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000742
743 if (tmp == NULL)
744 tmp = (char *) fileName;
745 else
746 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000747 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000748 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000749 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000750 return (FALSE);
751 }
Erik Andersend387d011999-12-21 02:55:11 +0000752 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000753 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000754}
755
Erik Andersen02104321999-12-17 18:57:34 +0000756
Eric Andersen9f16d612000-06-12 23:11:16 +0000757/*======================================================================*/
758
759struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000760{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000761 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000762 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000763
764#if defined(BB_USE_PLT_ENTRIES)
765 f->plt = NULL;
766#endif
767#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000768 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000769#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000770#if defined(__mips__)
771 f->mips_hi16_list = NULL;
772#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000773
Eric Andersen9f16d612000-06-12 23:11:16 +0000774 return &f->root;
775}
776
777struct obj_section *arch_new_section(void)
778{
779 return xmalloc(sizeof(struct obj_section));
780}
781
782struct obj_symbol *arch_new_symbol(void)
783{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000784 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000785 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000786
787#if defined(BB_USE_PLT_ENTRIES)
788 memset(&sym->pltent, 0, sizeof(sym->pltent));
789#endif
790#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000791 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000792#endif
793
Eric Andersen9f16d612000-06-12 23:11:16 +0000794 return &sym->root;
795}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000796
Eric Andersen9f16d612000-06-12 23:11:16 +0000797enum obj_reloc
798arch_apply_relocation(struct obj_file *f,
799 struct obj_section *targsec,
800 struct obj_section *symsec,
801 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000802 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000803{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000804 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000805#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000806 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000807#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000808
Eric Andersen21adca72000-12-06 18:18:26 +0000809 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
810 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000811#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000812 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000813#endif
814#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000815 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000817 unsigned long *ip;
818#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000819 enum obj_reloc ret = obj_reloc_ok;
820
821 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000822
823/* even though these constants seem to be the same for
824 the i386 and the sh, we "#if define" them for clarity
825 and in case that ever changes */
826#if defined(__sh__)
827 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000828#elif defined(__arm__)
829 case R_ARM_NONE:
830#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 case R_386_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000832#elif defined(__powerpc__)
833 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000834#elif defined(__mips__)
835 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000836#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000837 break;
838
Eric Andersenfe4208f2000-09-24 03:44:29 +0000839#if defined(__sh__)
840 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000841#elif defined(__arm__)
842 case R_ARM_ABS32:
843#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000844 case R_386_32:
845#elif defined(__powerpc__)
846 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000847#elif defined(__mips__)
848 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000849#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000850 *loc += v;
851 break;
852
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000853#if defined(__powerpc__)
854 case R_PPC_ADDR16_HA:
855 *(unsigned short *)loc = (v + 0x8000) >> 16;
856 break;
857
858 case R_PPC_ADDR16_HI:
859 *(unsigned short *)loc = v >> 16;
860 break;
861
862 case R_PPC_ADDR16_LO:
863 *(unsigned short *)loc = v;
864 break;
865#endif
866
Eric Andersen2bf658d2001-02-24 20:01:53 +0000867#if defined(__mips__)
868 case R_MIPS_26:
869 if (v % 4)
870 ret = obj_reloc_dangerous;
871 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
872 ret = obj_reloc_overflow;
873 *loc =
874 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
875 0x03ffffff);
876 break;
877
878 case R_MIPS_HI16:
879 {
880 struct mips_hi16 *n;
881
882 /* We cannot relocate this one now because we don't know the value
883 of the carry we need to add. Save the information, and let LO16
884 do the actual relocation. */
885 n = (struct mips_hi16 *) xmalloc(sizeof *n);
886 n->addr = loc;
887 n->value = v;
888 n->next = ifile->mips_hi16_list;
889 ifile->mips_hi16_list = n;
890 break;
891 }
892
893 case R_MIPS_LO16:
894 {
895 unsigned long insnlo = *loc;
896 Elf32_Addr val, vallo;
897
898 /* Sign extend the addend we extract from the lo insn. */
899 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
900
901 if (ifile->mips_hi16_list != NULL) {
902 struct mips_hi16 *l;
903
904 l = ifile->mips_hi16_list;
905 while (l != NULL) {
906 struct mips_hi16 *next;
907 unsigned long insn;
908
909 /* The value for the HI16 had best be the same. */
910 assert(v == l->value);
911
912 /* Do the HI16 relocation. Note that we actually don't
913 need to know anything about the LO16 itself, except where
914 to find the low 16 bits of the addend needed by the LO16. */
915 insn = *l->addr;
916 val =
917 ((insn & 0xffff) << 16) +
918 vallo;
919 val += v;
920
921 /* Account for the sign extension that will happen in the
922 low bits. */
923 val =
924 ((val >> 16) +
925 ((val & 0x8000) !=
926 0)) & 0xffff;
927
928 insn = (insn & ~0xffff) | val;
929 *l->addr = insn;
930
931 next = l->next;
932 free(l);
933 l = next;
934 }
935
936 ifile->mips_hi16_list = NULL;
937 }
938
939 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
940 val = v + vallo;
941 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
942 *loc = insnlo;
943 break;
944 }
945#endif
946
Eric Andersen21adca72000-12-06 18:18:26 +0000947#if defined(__arm__)
948#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000949 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000950 *loc += v - dot;
951 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000952#elif defined(__i386__)
953 case R_386_PLT32:
954 case R_386_PC32:
955 *loc += v - dot;
956 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000957#elif defined(__powerpc__)
958 case R_PPC_REL32:
959 *loc = v - dot;
960 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000961#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000962
Eric Andersenfe4208f2000-09-24 03:44:29 +0000963#if defined(__sh__)
964 case R_SH_PLT32:
965 *loc = v - dot;
966 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000967#elif defined(__i386__)
968#endif
969
970#if defined(BB_USE_PLT_ENTRIES)
971
972#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000973 case R_ARM_PC24:
974 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000975#endif
976#if defined(__powerpc__)
977 case R_PPC_REL24:
978#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000979 /* find the plt entry and initialize it if necessary */
980 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000981
982 pe = (struct arch_plt_entry*) &isym->pltent;
983
Eric Andersen21adca72000-12-06 18:18:26 +0000984 if (! pe->inited) {
985 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000986
987 /* generate some machine code */
988
989#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000990 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
991 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000992#endif
993#if defined(__powerpc__)
994 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
995 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
996 ip[2] = 0x7d6903a6; /* mtctr r11 */
997 ip[3] = 0x4e800420; /* bctr */
998#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000999 pe->inited = 1;
1000 }
1001
1002 /* relative distance to target */
1003 v -= dot;
1004 /* if the target is too far away.... */
1005 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1006 /* go via the plt */
1007 v = plt + pe->offset - dot;
1008 }
1009 if (v & 3)
1010 ret = obj_reloc_dangerous;
1011
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001012 /* merge the offset into the instruction. */
1013#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001014 /* Convert to words. */
1015 v >>= 2;
1016
Eric Andersen21adca72000-12-06 18:18:26 +00001017 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001018#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001019#if defined(__powerpc__)
1020 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1021#endif
1022 break;
1023#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001024
Eric Andersen21adca72000-12-06 18:18:26 +00001025#if defined(__arm__)
1026#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001027 case R_SH_GLOB_DAT:
1028 case R_SH_JMP_SLOT:
1029 *loc = v;
1030 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001031#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001032 case R_386_GLOB_DAT:
1033 case R_386_JMP_SLOT:
1034 *loc = v;
1035 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001036#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001037
Eric Andersen21adca72000-12-06 18:18:26 +00001038#if defined(__arm__)
1039#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001040 case R_SH_RELATIVE:
1041 *loc += f->baseaddr + rel->r_addend;
1042 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001043#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001044 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001045 *loc += f->baseaddr;
1046 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001047#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001048
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001049#if defined(BB_USE_GOT_ENTRIES)
1050
Eric Andersenfe4208f2000-09-24 03:44:29 +00001051#if defined(__sh__)
1052 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001053#elif defined(__arm__)
1054 case R_ARM_GOTPC:
1055#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001056 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001058 assert(got != 0);
1059#if defined(__sh__)
1060 *loc += got - dot + rel->r_addend;;
1061#elif defined(__i386__) || defined(__arm__)
1062 *loc += got - dot;
1063#endif
1064 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001065
Eric Andersenfe4208f2000-09-24 03:44:29 +00001066#if defined(__sh__)
1067 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001068#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001069 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001070#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001071 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001072#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001073 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001074 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001075 if (!isym->gotent.reloc_done) {
1076 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001077 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001078 }
Eric Andersen21adca72000-12-06 18:18:26 +00001079 /* make the reloc with_respect_to_.got */
1080#if defined(__sh__)
1081 *loc += isym->gotent.offset + rel->r_addend;
1082#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001083 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001084#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001085 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001086
Eric Andersen21adca72000-12-06 18:18:26 +00001087 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001088#if defined(__sh__)
1089 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001090#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001091 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001092#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001093 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001094#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001095 assert(got != 0);
1096 *loc += v - got;
1097 break;
1098
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001099#endif /* BB_USE_GOT_ENTRIES */
1100
Eric Andersen9f16d612000-06-12 23:11:16 +00001101 default:
Eric Andersen21125542000-12-13 16:41:29 +00001102 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001103 ret = obj_reloc_unhandled;
1104 break;
1105 }
1106
1107 return ret;
1108}
1109
1110int arch_create_got(struct obj_file *f)
1111{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001112#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001113 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001114 int i;
1115#if defined(BB_USE_GOT_ENTRIES)
1116 int got_offset = 0, gotneeded = 0;
1117#endif
1118#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001119 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001120#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001121 struct obj_section *relsec, *symsec, *strsec;
1122 ElfW(RelM) *rel, *relend;
1123 ElfW(Sym) *symtab, *extsym;
1124 const char *strtab, *name;
1125 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001126
Eric Andersen21adca72000-12-06 18:18:26 +00001127 for (i = 0; i < f->header.e_shnum; ++i) {
1128 relsec = f->sections[i];
1129 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001130 continue;
1131
Eric Andersen21adca72000-12-06 18:18:26 +00001132 symsec = f->sections[relsec->header.sh_link];
1133 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001134
Eric Andersen21adca72000-12-06 18:18:26 +00001135 rel = (ElfW(RelM) *) relsec->contents;
1136 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1137 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001138 strtab = (const char *) strsec->contents;
1139
1140 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001141 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001142
1143 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001144#if defined(__arm__)
1145 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001146 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001147#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001148 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001149 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001150#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001151 case R_386_GOT32:
1152 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001153#endif
1154
1155#if defined(__powerpc__)
1156 case R_PPC_REL24:
1157 pltneeded = 1;
1158 break;
1159#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001160
1161#if defined(__arm__)
1162 case R_ARM_PC24:
1163 case R_ARM_PLT32:
1164 pltneeded = 1;
1165 break;
1166
1167 case R_ARM_GOTPC:
1168 case R_ARM_GOTOFF:
1169 gotneeded = 1;
1170 if (got_offset == 0)
1171 got_offset = 4;
1172#elif defined(__sh__)
1173 case R_SH_GOTPC:
1174 case R_SH_GOTOFF:
1175 gotneeded = 1;
1176#elif defined(__i386__)
1177 case R_386_GOTPC:
1178 case R_386_GOTOFF:
1179 gotneeded = 1;
1180#endif
1181
1182 default:
1183 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001184 }
1185
Eric Andersen21adca72000-12-06 18:18:26 +00001186 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001187 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001188 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001189 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001190 }
1191 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001192#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001193 if (!intsym->gotent.offset_done) {
1194 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001195 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001196 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001197 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001198#endif
1199#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001200 if (pltneeded && intsym->pltent.allocated == 0) {
1201 intsym->pltent.allocated = 1;
1202 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001203 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001204 intsym->pltent.inited = 0;
1205 pltneeded = 0;
1206 }
1207#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001208 }
1209 }
Eric Andersen21adca72000-12-06 18:18:26 +00001210
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001211#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001212 if (got_offset) {
1213 struct obj_section* relsec = obj_find_section(f, ".got");
1214
1215 if (relsec) {
1216 obj_extend_section(relsec, got_offset);
1217 } else {
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001218 relsec = obj_create_alloced_section(f, ".got",
1219 BB_GOT_ENTRY_SIZE,
1220 got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001221 assert(relsec);
1222 }
1223
1224 ifile->got = relsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001225 }
Eric Andersen21adca72000-12-06 18:18:26 +00001226#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001227
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001228#if defined(BB_USE_PLT_ENTRIES)
1229 if (plt_offset)
1230 ifile->plt = obj_create_alloced_section(f, ".plt",
1231 BB_PLT_ENTRY_SIZE,
1232 plt_offset);
1233#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001234#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001235 return 1;
1236}
1237
1238int arch_init_module(struct obj_file *f, struct new_module *mod)
1239{
1240 return 1;
1241}
1242
1243
1244/*======================================================================*/
1245
1246/* Standard ELF hash function. */
1247inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1248{
1249 unsigned long h = 0;
1250 unsigned long g;
1251 unsigned char ch;
1252
1253 while (n > 0) {
1254 ch = *name++;
1255 h = (h << 4) + ch;
1256 if ((g = (h & 0xf0000000)) != 0) {
1257 h ^= g >> 24;
1258 h &= ~g;
1259 }
1260 n--;
1261 }
1262 return h;
1263}
1264
1265unsigned long obj_elf_hash(const char *name)
1266{
1267 return obj_elf_hash_n(name, strlen(name));
1268}
1269
1270#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1271/* Get the kernel version in the canonical integer form. */
1272
1273static int get_kernel_version(char str[STRVERSIONLEN])
1274{
1275 struct utsname uts_info;
1276 char *p, *q;
1277 int a, b, c;
1278
1279 if (uname(&uts_info) < 0)
1280 return -1;
1281 strncpy(str, uts_info.release, STRVERSIONLEN);
1282 p = uts_info.release;
1283
1284 a = strtoul(p, &p, 10);
1285 if (*p != '.')
1286 return -1;
1287 b = strtoul(p + 1, &p, 10);
1288 if (*p != '.')
1289 return -1;
1290 c = strtoul(p + 1, &q, 10);
1291 if (p + 1 == q)
1292 return -1;
1293
1294 return a << 16 | b << 8 | c;
1295}
1296
1297/* String comparison for non-co-versioned kernel and module. */
1298
1299static int ncv_strcmp(const char *a, const char *b)
1300{
1301 size_t alen = strlen(a), blen = strlen(b);
1302
1303 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1304 return strncmp(a, b, alen);
1305 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1306 return strncmp(a, b, blen);
1307 else
1308 return strcmp(a, b);
1309}
1310
1311/* String hashing for non-co-versioned kernel and module. Here
1312 we are simply forced to drop the crc from the hash. */
1313
1314static unsigned long ncv_symbol_hash(const char *str)
1315{
1316 size_t len = strlen(str);
1317 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1318 len -= 10;
1319 return obj_elf_hash_n(str, len);
1320}
1321
1322void
1323obj_set_symbol_compare(struct obj_file *f,
1324 int (*cmp) (const char *, const char *),
1325 unsigned long (*hash) (const char *))
1326{
1327 if (cmp)
1328 f->symbol_cmp = cmp;
1329 if (hash) {
1330 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1331 int i;
1332
1333 f->symbol_hash = hash;
1334
1335 memcpy(tmptab, f->symtab, sizeof(tmptab));
1336 memset(f->symtab, 0, sizeof(f->symtab));
1337
1338 for (i = 0; i < HASH_BUCKETS; ++i)
1339 for (sym = tmptab[i]; sym; sym = next) {
1340 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1341 next = sym->next;
1342 sym->next = f->symtab[h];
1343 f->symtab[h] = sym;
1344 }
1345 }
1346}
1347
1348#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1349
1350
1351struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1352 unsigned long symidx, int info,
1353 int secidx, ElfW(Addr) value,
1354 unsigned long size)
1355{
1356 struct obj_symbol *sym;
1357 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1358 int n_type = ELFW(ST_TYPE) (info);
1359 int n_binding = ELFW(ST_BIND) (info);
1360
1361 for (sym = f->symtab[hash]; sym; sym = sym->next)
1362 if (f->symbol_cmp(sym->name, name) == 0) {
1363 int o_secidx = sym->secidx;
1364 int o_info = sym->info;
1365 int o_type = ELFW(ST_TYPE) (o_info);
1366 int o_binding = ELFW(ST_BIND) (o_info);
1367
1368 /* A redefinition! Is it legal? */
1369
1370 if (secidx == SHN_UNDEF)
1371 return sym;
1372 else if (o_secidx == SHN_UNDEF)
1373 goto found;
1374 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1375 /* Cope with local and global symbols of the same name
1376 in the same object file, as might have been created
1377 by ld -r. The only reason locals are now seen at this
1378 level at all is so that we can do semi-sensible things
1379 with parameters. */
1380
1381 struct obj_symbol *nsym, **p;
1382
1383 nsym = arch_new_symbol();
1384 nsym->next = sym->next;
1385 nsym->ksymidx = -1;
1386
1387 /* Excise the old (local) symbol from the hash chain. */
1388 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1389 continue;
1390 *p = sym = nsym;
1391 goto found;
1392 } else if (n_binding == STB_LOCAL) {
1393 /* Another symbol of the same name has already been defined.
1394 Just add this to the local table. */
1395 sym = arch_new_symbol();
1396 sym->next = NULL;
1397 sym->ksymidx = -1;
1398 f->local_symtab[symidx] = sym;
1399 goto found;
1400 } else if (n_binding == STB_WEAK)
1401 return sym;
1402 else if (o_binding == STB_WEAK)
1403 goto found;
1404 /* Don't unify COMMON symbols with object types the programmer
1405 doesn't expect. */
1406 else if (secidx == SHN_COMMON
1407 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1408 return sym;
1409 else if (o_secidx == SHN_COMMON
1410 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1411 goto found;
1412 else {
1413 /* Don't report an error if the symbol is coming from
1414 the kernel or some external module. */
1415 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001416 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001417 return sym;
1418 }
1419 }
1420
1421 /* Completely new symbol. */
1422 sym = arch_new_symbol();
1423 sym->next = f->symtab[hash];
1424 f->symtab[hash] = sym;
1425 sym->ksymidx = -1;
1426
1427 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1428 f->local_symtab[symidx] = sym;
1429
1430 found:
1431 sym->name = name;
1432 sym->value = value;
1433 sym->size = size;
1434 sym->secidx = secidx;
1435 sym->info = info;
1436
1437 return sym;
1438}
1439
1440struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1441{
1442 struct obj_symbol *sym;
1443 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1444
1445 for (sym = f->symtab[hash]; sym; sym = sym->next)
1446 if (f->symbol_cmp(sym->name, name) == 0)
1447 return sym;
1448
1449 return NULL;
1450}
1451
1452ElfW(Addr)
1453 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1454{
1455 if (sym) {
1456 if (sym->secidx >= SHN_LORESERVE)
1457 return sym->value;
1458
1459 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1460 } else {
1461 /* As a special case, a NULL sym has value zero. */
1462 return 0;
1463 }
1464}
1465
1466struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1467{
1468 int i, n = f->header.e_shnum;
1469
1470 for (i = 0; i < n; ++i)
1471 if (strcmp(f->sections[i]->name, name) == 0)
1472 return f->sections[i];
1473
1474 return NULL;
1475}
1476
1477static int obj_load_order_prio(struct obj_section *a)
1478{
1479 unsigned long af, ac;
1480
1481 af = a->header.sh_flags;
1482
1483 ac = 0;
1484 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1485 strcmp(a->name + 5, ".init"))
1486 ac |= 32;
1487 if (af & SHF_ALLOC)
1488 ac |= 16;
1489 if (!(af & SHF_WRITE))
1490 ac |= 8;
1491 if (af & SHF_EXECINSTR)
1492 ac |= 4;
1493 if (a->header.sh_type != SHT_NOBITS)
1494 ac |= 2;
1495
1496 return ac;
1497}
1498
1499void
1500obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1501{
1502 struct obj_section **p;
1503 int prio = obj_load_order_prio(sec);
1504 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1505 if (obj_load_order_prio(*p) < prio)
1506 break;
1507 sec->load_next = *p;
1508 *p = sec;
1509}
1510
1511struct obj_section *obj_create_alloced_section(struct obj_file *f,
1512 const char *name,
1513 unsigned long align,
1514 unsigned long size)
1515{
1516 int newidx = f->header.e_shnum++;
1517 struct obj_section *sec;
1518
1519 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1520 f->sections[newidx] = sec = arch_new_section();
1521
1522 memset(sec, 0, sizeof(*sec));
1523 sec->header.sh_type = SHT_PROGBITS;
1524 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1525 sec->header.sh_size = size;
1526 sec->header.sh_addralign = align;
1527 sec->name = name;
1528 sec->idx = newidx;
1529 if (size)
1530 sec->contents = xmalloc(size);
1531
1532 obj_insert_section_load_order(f, sec);
1533
1534 return sec;
1535}
1536
1537struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1538 const char *name,
1539 unsigned long align,
1540 unsigned long size)
1541{
1542 int newidx = f->header.e_shnum++;
1543 struct obj_section *sec;
1544
1545 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1546 f->sections[newidx] = sec = arch_new_section();
1547
1548 memset(sec, 0, sizeof(*sec));
1549 sec->header.sh_type = SHT_PROGBITS;
1550 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1551 sec->header.sh_size = size;
1552 sec->header.sh_addralign = align;
1553 sec->name = name;
1554 sec->idx = newidx;
1555 if (size)
1556 sec->contents = xmalloc(size);
1557
1558 sec->load_next = f->load_order;
1559 f->load_order = sec;
1560 if (f->load_order_search_start == &f->load_order)
1561 f->load_order_search_start = &sec->load_next;
1562
1563 return sec;
1564}
1565
1566void *obj_extend_section(struct obj_section *sec, unsigned long more)
1567{
1568 unsigned long oldsize = sec->header.sh_size;
1569 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1570 return sec->contents + oldsize;
1571}
1572
1573
1574
1575/* Conditionally add the symbols from the given symbol set to the
1576 new module. */
1577
1578static int
1579add_symbols_from(
1580 struct obj_file *f,
1581 int idx, struct new_module_symbol *syms, size_t nsyms)
1582{
1583 struct new_module_symbol *s;
1584 size_t i;
1585 int used = 0;
1586
1587 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1588
1589 /* Only add symbols that are already marked external. If we
1590 override locals we may cause problems for argument initialization.
1591 We will also create a false dependency on the module. */
1592 struct obj_symbol *sym;
1593
1594 sym = obj_find_symbol(f, (char *) s->name);
1595 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1596 sym = obj_add_symbol(f, (char *) s->name, -1,
1597 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1598 idx, s->value, 0);
1599 /* Did our symbol just get installed? If so, mark the
1600 module as "used". */
1601 if (sym->secidx == idx)
1602 used = 1;
1603 }
1604 }
1605
1606 return used;
1607}
1608
1609static void add_kernel_symbols(struct obj_file *f)
1610{
1611 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001612 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001613
1614 /* Add module symbols first. */
1615
1616 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1617 if (m->nsyms
1618 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1619 m->nsyms)) m->used = 1, ++nused;
1620
1621 n_ext_modules_used = nused;
1622
1623 /* And finally the symbols from the kernel proper. */
1624
1625 if (nksyms)
1626 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1627}
1628
1629static char *get_modinfo_value(struct obj_file *f, const char *key)
1630{
1631 struct obj_section *sec;
1632 char *p, *v, *n, *ep;
1633 size_t klen = strlen(key);
1634
1635 sec = obj_find_section(f, ".modinfo");
1636 if (sec == NULL)
1637 return NULL;
1638 p = sec->contents;
1639 ep = p + sec->header.sh_size;
1640 while (p < ep) {
1641 v = strchr(p, '=');
1642 n = strchr(p, '\0');
1643 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001644 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001645 return v + 1;
1646 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001647 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001648 return n;
1649 }
1650 p = n + 1;
1651 }
1652
1653 return NULL;
1654}
1655
1656
1657/*======================================================================*/
1658/* Functions relating to module loading in pre 2.1 kernels. */
1659
1660static int
1661old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1662{
1663 while (argc > 0) {
1664 char *p, *q;
1665 struct obj_symbol *sym;
1666 int *loc;
1667
1668 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001669 if ((q = strchr(p, '=')) == NULL) {
1670 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001671 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001672 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001673 *q++ = '\0';
1674
1675 sym = obj_find_symbol(f, p);
1676
1677 /* Also check that the parameter was not resolved from the kernel. */
1678 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001679 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001680 return 0;
1681 }
1682
1683 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1684
1685 /* Do C quoting if we begin with a ". */
1686 if (*q == '"') {
1687 char *r, *str;
1688
1689 str = alloca(strlen(q));
1690 for (r = str, q++; *q != '"'; ++q, ++r) {
1691 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001692 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001693 return 0;
1694 } else if (*q == '\\')
1695 switch (*++q) {
1696 case 'a':
1697 *r = '\a';
1698 break;
1699 case 'b':
1700 *r = '\b';
1701 break;
1702 case 'e':
1703 *r = '\033';
1704 break;
1705 case 'f':
1706 *r = '\f';
1707 break;
1708 case 'n':
1709 *r = '\n';
1710 break;
1711 case 'r':
1712 *r = '\r';
1713 break;
1714 case 't':
1715 *r = '\t';
1716 break;
1717
1718 case '0':
1719 case '1':
1720 case '2':
1721 case '3':
1722 case '4':
1723 case '5':
1724 case '6':
1725 case '7':
1726 {
1727 int c = *q - '0';
1728 if (q[1] >= '0' && q[1] <= '7') {
1729 c = (c * 8) + *++q - '0';
1730 if (q[1] >= '0' && q[1] <= '7')
1731 c = (c * 8) + *++q - '0';
1732 }
1733 *r = c;
1734 }
1735 break;
1736
1737 default:
1738 *r = *q;
1739 break;
1740 } else
1741 *r = *q;
1742 }
1743 *r = '\0';
1744 obj_string_patch(f, sym->secidx, sym->value, str);
1745 } else if (*q >= '0' && *q <= '9') {
1746 do
1747 *loc++ = strtoul(q, &q, 0);
1748 while (*q++ == ',');
1749 } else {
1750 char *contents = f->sections[sym->secidx]->contents;
1751 char *loc = contents + sym->value;
1752 char *r; /* To search for commas */
1753
1754 /* Break the string with comas */
1755 while ((r = strchr(q, ',')) != (char *) NULL) {
1756 *r++ = '\0';
1757 obj_string_patch(f, sym->secidx, loc - contents, q);
1758 loc += sizeof(char *);
1759 q = r;
1760 }
1761
1762 /* last part */
1763 obj_string_patch(f, sym->secidx, loc - contents, q);
1764 }
1765
1766 argc--, argv++;
1767 }
1768
1769 return 1;
1770}
1771
1772#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1773static int old_is_module_checksummed(struct obj_file *f)
1774{
1775 return obj_find_symbol(f, "Using_Versions") != NULL;
1776}
1777/* Get the module's kernel version in the canonical integer form. */
1778
1779static int
1780old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1781{
1782 struct obj_symbol *sym;
1783 char *p, *q;
1784 int a, b, c;
1785
1786 sym = obj_find_symbol(f, "kernel_version");
1787 if (sym == NULL)
1788 return -1;
1789
1790 p = f->sections[sym->secidx]->contents + sym->value;
1791 strncpy(str, p, STRVERSIONLEN);
1792
1793 a = strtoul(p, &p, 10);
1794 if (*p != '.')
1795 return -1;
1796 b = strtoul(p + 1, &p, 10);
1797 if (*p != '.')
1798 return -1;
1799 c = strtoul(p + 1, &q, 10);
1800 if (p + 1 == q)
1801 return -1;
1802
1803 return a << 16 | b << 8 | c;
1804}
1805
1806#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1807
Eric Andersenf5d5e772001-01-24 23:34:48 +00001808#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001809
1810/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1811
Eric Andersen8c185f92000-09-22 00:38:07 +00001812static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001813{
1814 struct old_kernel_sym *ks, *k;
1815 struct new_module_symbol *s;
1816 struct external_module *mod;
1817 int nks, nms, nmod, i;
1818
1819 nks = get_kernel_syms(NULL);
1820 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001821 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001822 return 0;
1823 }
1824
1825 ks = k = xmalloc(nks * sizeof(*ks));
1826
1827 if (get_kernel_syms(ks) != nks) {
1828 perror("inconsistency with get_kernel_syms -- is someone else "
1829 "playing with modules?");
1830 free(ks);
1831 return 0;
1832 }
1833
1834 /* Collect the module information. */
1835
1836 mod = NULL;
1837 nmod = -1;
1838
1839 while (k->name[0] == '#' && k->name[1]) {
1840 struct old_kernel_sym *k2;
1841 struct new_module_symbol *s;
1842
1843 /* Find out how many symbols this module has. */
1844 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1845 continue;
1846 nms = k2 - k - 1;
1847
1848 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1849 mod[nmod].name = k->name + 1;
1850 mod[nmod].addr = k->value;
1851 mod[nmod].used = 0;
1852 mod[nmod].nsyms = nms;
1853 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1854
1855 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1856 s->name = (unsigned long) k->name;
1857 s->value = k->value;
1858 }
1859
1860 k = k2;
1861 }
1862
1863 ext_modules = mod;
1864 n_ext_modules = nmod + 1;
1865
1866 /* Now collect the symbols for the kernel proper. */
1867
1868 if (k->name[0] == '#')
1869 ++k;
1870
1871 nksyms = nms = nks - (k - ks);
1872 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1873
1874 for (i = 0; i < nms; ++i, ++s, ++k) {
1875 s->name = (unsigned long) k->name;
1876 s->value = k->value;
1877 }
1878
1879 return 1;
1880}
1881
1882/* Return the kernel symbol checksum version, or zero if not used. */
1883
1884static int old_is_kernel_checksummed(void)
1885{
1886 /* Using_Versions is the first symbol. */
1887 if (nksyms > 0
1888 && strcmp((char *) ksyms[0].name,
1889 "Using_Versions") == 0) return ksyms[0].value;
1890 else
1891 return 0;
1892}
1893
1894
1895static int old_create_mod_use_count(struct obj_file *f)
1896{
1897 struct obj_section *sec;
1898
1899 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1900 sizeof(long));
1901
1902 obj_add_symbol(f, "mod_use_count_", -1,
1903 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1904 sizeof(long));
1905
1906 return 1;
1907}
1908
1909static int
1910old_init_module(const char *m_name, struct obj_file *f,
1911 unsigned long m_size)
1912{
1913 char *image;
1914 struct old_mod_routines routines;
1915 struct old_symbol_table *symtab;
1916 int ret;
1917
1918 /* Create the symbol table */
1919 {
1920 int nsyms = 0, strsize = 0, total;
1921
1922 /* Size things first... */
1923 if (flag_export) {
1924 int i;
1925 for (i = 0; i < HASH_BUCKETS; ++i) {
1926 struct obj_symbol *sym;
1927 for (sym = f->symtab[i]; sym; sym = sym->next)
1928 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1929 && sym->secidx <= SHN_HIRESERVE)
1930 {
1931 sym->ksymidx = nsyms++;
1932 strsize += strlen(sym->name) + 1;
1933 }
1934 }
1935 }
1936
1937 total = (sizeof(struct old_symbol_table)
1938 + nsyms * sizeof(struct old_module_symbol)
1939 + n_ext_modules_used * sizeof(struct old_module_ref)
1940 + strsize);
1941 symtab = xmalloc(total);
1942 symtab->size = total;
1943 symtab->n_symbols = nsyms;
1944 symtab->n_refs = n_ext_modules_used;
1945
1946 if (flag_export && nsyms) {
1947 struct old_module_symbol *ksym;
1948 char *str;
1949 int i;
1950
1951 ksym = symtab->symbol;
1952 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1953 + n_ext_modules_used * sizeof(struct old_module_ref));
1954
1955 for (i = 0; i < HASH_BUCKETS; ++i) {
1956 struct obj_symbol *sym;
1957 for (sym = f->symtab[i]; sym; sym = sym->next)
1958 if (sym->ksymidx >= 0) {
1959 ksym->addr = obj_symbol_final_value(f, sym);
1960 ksym->name =
1961 (unsigned long) str - (unsigned long) symtab;
1962
Matt Kraai70a78552001-01-04 02:00:17 +00001963 strcpy(str, sym->name);
1964 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001965 ksym++;
1966 }
1967 }
1968 }
1969
1970 if (n_ext_modules_used) {
1971 struct old_module_ref *ref;
1972 int i;
1973
1974 ref = (struct old_module_ref *)
1975 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1976
1977 for (i = 0; i < n_ext_modules; ++i)
1978 if (ext_modules[i].used)
1979 ref++->module = ext_modules[i].addr;
1980 }
1981 }
1982
1983 /* Fill in routines. */
1984
1985 routines.init =
1986 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1987 routines.cleanup =
1988 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1989
1990 /* Whew! All of the initialization is complete. Collect the final
1991 module image and give it to the kernel. */
1992
1993 image = xmalloc(m_size);
1994 obj_create_image(f, image);
1995
1996 /* image holds the complete relocated module, accounting correctly for
1997 mod_use_count. However the old module kernel support assume that
1998 it is receiving something which does not contain mod_use_count. */
1999 ret = old_sys_init_module(m_name, image + sizeof(long),
2000 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2001 : 0), &routines, symtab);
2002 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002003 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002004
2005 free(image);
2006 free(symtab);
2007
2008 return ret == 0;
2009}
2010
2011#else
2012
2013#define old_create_mod_use_count(x) TRUE
2014#define old_init_module(x, y, z) TRUE
2015
Eric Andersenf5d5e772001-01-24 23:34:48 +00002016#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002017
2018
2019
2020/*======================================================================*/
2021/* Functions relating to module loading after 2.1.18. */
2022
2023static int
2024new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2025{
2026 while (argc > 0) {
2027 char *p, *q, *key;
2028 struct obj_symbol *sym;
2029 char *contents, *loc;
2030 int min, max, n;
2031
2032 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002033 if ((q = strchr(p, '=')) == NULL) {
2034 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002035 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002036 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002037
2038 key = alloca(q - p + 6);
2039 memcpy(key, "parm_", 5);
2040 memcpy(key + 5, p, q - p);
2041 key[q - p + 5] = 0;
2042
2043 p = get_modinfo_value(f, key);
2044 key += 5;
2045 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002046 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002047 return 0;
2048 }
2049
2050 sym = obj_find_symbol(f, key);
2051
2052 /* Also check that the parameter was not resolved from the kernel. */
2053 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002054 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002055 return 0;
2056 }
2057
2058 if (isdigit(*p)) {
2059 min = strtoul(p, &p, 10);
2060 if (*p == '-')
2061 max = strtoul(p + 1, &p, 10);
2062 else
2063 max = min;
2064 } else
2065 min = max = 1;
2066
2067 contents = f->sections[sym->secidx]->contents;
2068 loc = contents + sym->value;
2069 n = (*++q != '\0');
2070
2071 while (1) {
2072 if ((*p == 's') || (*p == 'c')) {
2073 char *str;
2074
2075 /* Do C quoting if we begin with a ", else slurp the lot. */
2076 if (*q == '"') {
2077 char *r;
2078
2079 str = alloca(strlen(q));
2080 for (r = str, q++; *q != '"'; ++q, ++r) {
2081 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002082 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002083 key);
2084 return 0;
2085 } else if (*q == '\\')
2086 switch (*++q) {
2087 case 'a':
2088 *r = '\a';
2089 break;
2090 case 'b':
2091 *r = '\b';
2092 break;
2093 case 'e':
2094 *r = '\033';
2095 break;
2096 case 'f':
2097 *r = '\f';
2098 break;
2099 case 'n':
2100 *r = '\n';
2101 break;
2102 case 'r':
2103 *r = '\r';
2104 break;
2105 case 't':
2106 *r = '\t';
2107 break;
2108
2109 case '0':
2110 case '1':
2111 case '2':
2112 case '3':
2113 case '4':
2114 case '5':
2115 case '6':
2116 case '7':
2117 {
2118 int c = *q - '0';
2119 if (q[1] >= '0' && q[1] <= '7') {
2120 c = (c * 8) + *++q - '0';
2121 if (q[1] >= '0' && q[1] <= '7')
2122 c = (c * 8) + *++q - '0';
2123 }
2124 *r = c;
2125 }
2126 break;
2127
2128 default:
2129 *r = *q;
2130 break;
2131 } else
2132 *r = *q;
2133 }
2134 *r = '\0';
2135 ++q;
2136 } else {
2137 char *r;
2138
2139 /* In this case, the string is not quoted. We will break
2140 it using the coma (like for ints). If the user wants to
2141 include comas in a string, he just has to quote it */
2142
2143 /* Search the next coma */
2144 r = strchr(q, ',');
2145
2146 /* Found ? */
2147 if (r != (char *) NULL) {
2148 /* Recopy the current field */
2149 str = alloca(r - q + 1);
2150 memcpy(str, q, r - q);
2151
2152 /* I don't know if it is usefull, as the previous case
2153 doesn't null terminate the string ??? */
2154 str[r - q] = '\0';
2155
2156 /* Keep next fields */
2157 q = r;
2158 } else {
2159 /* last string */
2160 str = q;
2161 q = "";
2162 }
2163 }
2164
2165 if (*p == 's') {
2166 /* Normal string */
2167 obj_string_patch(f, sym->secidx, loc - contents, str);
2168 loc += tgt_sizeof_char_p;
2169 } else {
2170 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002171 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002172
2173 /* Get the size of each member */
2174 /* Probably we should do that outside the loop ? */
2175 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002176 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002177 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002178 return 0;
2179 }
2180 charssize = strtoul(p + 1, (char **) NULL, 10);
2181
2182 /* Check length */
2183 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002184 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002185 charssize - 1);
2186 return 0;
2187 }
2188
2189 /* Copy to location */
2190 strcpy((char *) loc, str);
2191 loc += charssize;
2192 }
2193 } else {
2194 long v = strtoul(q, &q, 0);
2195 switch (*p) {
2196 case 'b':
2197 *loc++ = v;
2198 break;
2199 case 'h':
2200 *(short *) loc = v;
2201 loc += tgt_sizeof_short;
2202 break;
2203 case 'i':
2204 *(int *) loc = v;
2205 loc += tgt_sizeof_int;
2206 break;
2207 case 'l':
2208 *(long *) loc = v;
2209 loc += tgt_sizeof_long;
2210 break;
2211
2212 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002213 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002214 return 0;
2215 }
2216 }
2217
2218 retry_end_of_value:
2219 switch (*q) {
2220 case '\0':
2221 goto end_of_arg;
2222
2223 case ' ':
2224 case '\t':
2225 case '\n':
2226 case '\r':
2227 ++q;
2228 goto retry_end_of_value;
2229
2230 case ',':
2231 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002232 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002233 return 0;
2234 }
2235 ++q;
2236 break;
2237
2238 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002239 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002240 return 0;
2241 }
2242 }
2243
2244 end_of_arg:
2245 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002246 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002247 return 0;
2248 }
2249
2250 argc--, argv++;
2251 }
2252
2253 return 1;
2254}
2255
2256#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2257static int new_is_module_checksummed(struct obj_file *f)
2258{
2259 const char *p = get_modinfo_value(f, "using_checksums");
2260 if (p)
2261 return atoi(p);
2262 else
2263 return 0;
2264}
2265
2266/* Get the module's kernel version in the canonical integer form. */
2267
2268static int
2269new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2270{
2271 char *p, *q;
2272 int a, b, c;
2273
2274 p = get_modinfo_value(f, "kernel_version");
2275 if (p == NULL)
2276 return -1;
2277 strncpy(str, p, STRVERSIONLEN);
2278
2279 a = strtoul(p, &p, 10);
2280 if (*p != '.')
2281 return -1;
2282 b = strtoul(p + 1, &p, 10);
2283 if (*p != '.')
2284 return -1;
2285 c = strtoul(p + 1, &q, 10);
2286 if (p + 1 == q)
2287 return -1;
2288
2289 return a << 16 | b << 8 | c;
2290}
2291
2292#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2293
2294
Eric Andersenf5d5e772001-01-24 23:34:48 +00002295#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002296
2297/* Fetch the loaded modules, and all currently exported symbols. */
2298
2299static int new_get_kernel_symbols(void)
2300{
2301 char *module_names, *mn;
2302 struct external_module *modules, *m;
2303 struct new_module_symbol *syms, *s;
2304 size_t ret, bufsize, nmod, nsyms, i, j;
2305
2306 /* Collect the loaded modules. */
2307
2308 module_names = xmalloc(bufsize = 256);
2309 retry_modules_load:
2310 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2311 if (errno == ENOSPC) {
2312 module_names = xrealloc(module_names, bufsize = ret);
2313 goto retry_modules_load;
2314 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002315 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002316 return 0;
2317 }
2318
2319 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002320
2321 /* Collect the modules' symbols. */
2322
Mark Whitley94fd4802001-03-12 23:08:34 +00002323 if (nmod){
2324 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2325 memset(modules, 0, nmod * sizeof(*modules));
2326 for (i = 0, mn = module_names, m = modules;
2327 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2328 struct new_module_info info;
2329
2330 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2331 if (errno == ENOENT) {
2332 /* The module was removed out from underneath us. */
2333 continue;
2334 }
2335 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002336 return 0;
2337 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002338
2339 syms = xmalloc(bufsize = 1024);
2340 retry_mod_sym_load:
2341 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2342 switch (errno) {
2343 case ENOSPC:
2344 syms = xrealloc(syms, bufsize = ret);
2345 goto retry_mod_sym_load;
2346 case ENOENT:
2347 /* The module was removed out from underneath us. */
2348 continue;
2349 default:
2350 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2351 return 0;
2352 }
2353 }
2354 nsyms = ret;
2355
2356 m->name = mn;
2357 m->addr = info.addr;
2358 m->nsyms = nsyms;
2359 m->syms = syms;
2360
2361 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2362 s->name += (unsigned long) syms;
2363 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002364 }
2365 }
2366
2367 /* Collect the kernel's symbols. */
2368
2369 syms = xmalloc(bufsize = 16 * 1024);
2370 retry_kern_sym_load:
2371 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2372 if (errno == ENOSPC) {
2373 syms = xrealloc(syms, bufsize = ret);
2374 goto retry_kern_sym_load;
2375 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002376 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002377 return 0;
2378 }
2379 nksyms = nsyms = ret;
2380 ksyms = syms;
2381
2382 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2383 s->name += (unsigned long) syms;
2384 }
2385 return 1;
2386}
2387
2388
2389/* Return the kernel symbol checksum version, or zero if not used. */
2390
2391static int new_is_kernel_checksummed(void)
2392{
2393 struct new_module_symbol *s;
2394 size_t i;
2395
2396 /* Using_Versions is not the first symbol, but it should be in there. */
2397
2398 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2399 if (strcmp((char *) s->name, "Using_Versions") == 0)
2400 return s->value;
2401
2402 return 0;
2403}
2404
2405
2406static int new_create_this_module(struct obj_file *f, const char *m_name)
2407{
2408 struct obj_section *sec;
2409
2410 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2411 sizeof(struct new_module));
2412 memset(sec->contents, 0, sizeof(struct new_module));
2413
2414 obj_add_symbol(f, "__this_module", -1,
2415 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2416 sizeof(struct new_module));
2417
2418 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2419 m_name);
2420
2421 return 1;
2422}
2423
2424
2425static int new_create_module_ksymtab(struct obj_file *f)
2426{
2427 struct obj_section *sec;
2428 int i;
2429
2430 /* We must always add the module references. */
2431
2432 if (n_ext_modules_used) {
2433 struct new_module_ref *dep;
2434 struct obj_symbol *tm;
2435
2436 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2437 (sizeof(struct new_module_ref)
2438 * n_ext_modules_used));
2439 if (!sec)
2440 return 0;
2441
2442 tm = obj_find_symbol(f, "__this_module");
2443 dep = (struct new_module_ref *) sec->contents;
2444 for (i = 0; i < n_ext_modules; ++i)
2445 if (ext_modules[i].used) {
2446 dep->dep = ext_modules[i].addr;
2447 obj_symbol_patch(f, sec->idx,
2448 (char *) &dep->ref - sec->contents, tm);
2449 dep->next_ref = 0;
2450 ++dep;
2451 }
2452 }
2453
2454 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2455 size_t nsyms;
2456 int *loaded;
2457
2458 sec =
2459 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2460 0);
2461
2462 /* We don't want to export symbols residing in sections that
2463 aren't loaded. There are a number of these created so that
2464 we make sure certain module options don't appear twice. */
2465
2466 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2467 while (--i >= 0)
2468 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2469
2470 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2471 struct obj_symbol *sym;
2472 for (sym = f->symtab[i]; sym; sym = sym->next)
2473 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2474 && sym->secidx <= SHN_HIRESERVE
2475 && (sym->secidx >= SHN_LORESERVE
2476 || loaded[sym->secidx])) {
2477 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2478
2479 obj_symbol_patch(f, sec->idx, ofs, sym);
2480 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2481 sym->name);
2482
2483 nsyms++;
2484 }
2485 }
2486
2487 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2488 }
2489
2490 return 1;
2491}
2492
2493
2494static int
2495new_init_module(const char *m_name, struct obj_file *f,
2496 unsigned long m_size)
2497{
2498 struct new_module *module;
2499 struct obj_section *sec;
2500 void *image;
2501 int ret;
2502 tgt_long m_addr;
2503
2504 sec = obj_find_section(f, ".this");
2505 module = (struct new_module *) sec->contents;
2506 m_addr = sec->header.sh_addr;
2507
2508 module->size_of_struct = sizeof(*module);
2509 module->size = m_size;
2510 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2511
2512 sec = obj_find_section(f, "__ksymtab");
2513 if (sec && sec->header.sh_size) {
2514 module->syms = sec->header.sh_addr;
2515 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2516 }
2517
2518 if (n_ext_modules_used) {
2519 sec = obj_find_section(f, ".kmodtab");
2520 module->deps = sec->header.sh_addr;
2521 module->ndeps = n_ext_modules_used;
2522 }
2523
2524 module->init =
2525 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2526 module->cleanup =
2527 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2528
2529 sec = obj_find_section(f, "__ex_table");
2530 if (sec) {
2531 module->ex_table_start = sec->header.sh_addr;
2532 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2533 }
2534
2535 sec = obj_find_section(f, ".text.init");
2536 if (sec) {
2537 module->runsize = sec->header.sh_addr - m_addr;
2538 }
2539 sec = obj_find_section(f, ".data.init");
2540 if (sec) {
2541 if (!module->runsize ||
2542 module->runsize > sec->header.sh_addr - m_addr)
2543 module->runsize = sec->header.sh_addr - m_addr;
2544 }
2545
2546 if (!arch_init_module(f, module))
2547 return 0;
2548
2549 /* Whew! All of the initialization is complete. Collect the final
2550 module image and give it to the kernel. */
2551
2552 image = xmalloc(m_size);
2553 obj_create_image(f, image);
2554
2555 ret = new_sys_init_module(m_name, (struct new_module *) image);
2556 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002557 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002558
2559 free(image);
2560
2561 return ret == 0;
2562}
2563
2564#else
2565
2566#define new_init_module(x, y, z) TRUE
2567#define new_create_this_module(x, y) 0
2568#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002569#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002570
Eric Andersenf5d5e772001-01-24 23:34:48 +00002571#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002572
2573
2574/*======================================================================*/
2575
2576int
2577obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2578 const char *string)
2579{
2580 struct obj_string_patch *p;
2581 struct obj_section *strsec;
2582 size_t len = strlen(string) + 1;
2583 char *loc;
2584
2585 p = xmalloc(sizeof(*p));
2586 p->next = f->string_patches;
2587 p->reloc_secidx = secidx;
2588 p->reloc_offset = offset;
2589 f->string_patches = p;
2590
2591 strsec = obj_find_section(f, ".kstrtab");
2592 if (strsec == NULL) {
2593 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2594 p->string_offset = 0;
2595 loc = strsec->contents;
2596 } else {
2597 p->string_offset = strsec->header.sh_size;
2598 loc = obj_extend_section(strsec, len);
2599 }
2600 memcpy(loc, string, len);
2601
2602 return 1;
2603}
2604
2605int
2606obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2607 struct obj_symbol *sym)
2608{
2609 struct obj_symbol_patch *p;
2610
2611 p = xmalloc(sizeof(*p));
2612 p->next = f->symbol_patches;
2613 p->reloc_secidx = secidx;
2614 p->reloc_offset = offset;
2615 p->sym = sym;
2616 f->symbol_patches = p;
2617
2618 return 1;
2619}
2620
2621int obj_check_undefineds(struct obj_file *f)
2622{
2623 unsigned long i;
2624 int ret = 1;
2625
2626 for (i = 0; i < HASH_BUCKETS; ++i) {
2627 struct obj_symbol *sym;
2628 for (sym = f->symtab[i]; sym; sym = sym->next)
2629 if (sym->secidx == SHN_UNDEF) {
2630 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2631 sym->secidx = SHN_ABS;
2632 sym->value = 0;
2633 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002634 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002635 ret = 0;
2636 }
2637 }
2638 }
2639
2640 return ret;
2641}
2642
2643void obj_allocate_commons(struct obj_file *f)
2644{
2645 struct common_entry {
2646 struct common_entry *next;
2647 struct obj_symbol *sym;
2648 } *common_head = NULL;
2649
2650 unsigned long i;
2651
2652 for (i = 0; i < HASH_BUCKETS; ++i) {
2653 struct obj_symbol *sym;
2654 for (sym = f->symtab[i]; sym; sym = sym->next)
2655 if (sym->secidx == SHN_COMMON) {
2656 /* Collect all COMMON symbols and sort them by size so as to
2657 minimize space wasted by alignment requirements. */
2658 {
2659 struct common_entry **p, *n;
2660 for (p = &common_head; *p; p = &(*p)->next)
2661 if (sym->size <= (*p)->sym->size)
2662 break;
2663
2664 n = alloca(sizeof(*n));
2665 n->next = *p;
2666 n->sym = sym;
2667 *p = n;
2668 }
2669 }
2670 }
2671
2672 for (i = 1; i < f->local_symtab_size; ++i) {
2673 struct obj_symbol *sym = f->local_symtab[i];
2674 if (sym && sym->secidx == SHN_COMMON) {
2675 struct common_entry **p, *n;
2676 for (p = &common_head; *p; p = &(*p)->next)
2677 if (sym == (*p)->sym)
2678 break;
2679 else if (sym->size < (*p)->sym->size) {
2680 n = alloca(sizeof(*n));
2681 n->next = *p;
2682 n->sym = sym;
2683 *p = n;
2684 break;
2685 }
2686 }
2687 }
2688
2689 if (common_head) {
2690 /* Find the bss section. */
2691 for (i = 0; i < f->header.e_shnum; ++i)
2692 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2693 break;
2694
2695 /* If for some reason there hadn't been one, create one. */
2696 if (i == f->header.e_shnum) {
2697 struct obj_section *sec;
2698
2699 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2700 f->sections[i] = sec = arch_new_section();
2701 f->header.e_shnum = i + 1;
2702
2703 memset(sec, 0, sizeof(*sec));
2704 sec->header.sh_type = SHT_PROGBITS;
2705 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2706 sec->name = ".bss";
2707 sec->idx = i;
2708 }
2709
2710 /* Allocate the COMMONS. */
2711 {
2712 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2713 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2714 struct common_entry *c;
2715
2716 for (c = common_head; c; c = c->next) {
2717 ElfW(Addr) align = c->sym->value;
2718
2719 if (align > max_align)
2720 max_align = align;
2721 if (bss_size & (align - 1))
2722 bss_size = (bss_size | (align - 1)) + 1;
2723
2724 c->sym->secidx = i;
2725 c->sym->value = bss_size;
2726
2727 bss_size += c->sym->size;
2728 }
2729
2730 f->sections[i]->header.sh_size = bss_size;
2731 f->sections[i]->header.sh_addralign = max_align;
2732 }
2733 }
2734
2735 /* For the sake of patch relocation and parameter initialization,
2736 allocate zeroed data for NOBITS sections now. Note that after
2737 this we cannot assume NOBITS are really empty. */
2738 for (i = 0; i < f->header.e_shnum; ++i) {
2739 struct obj_section *s = f->sections[i];
2740 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002741 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002742 s->contents = memset(xmalloc(s->header.sh_size),
2743 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002744 else
2745 s->contents = NULL;
2746
Eric Andersen9f16d612000-06-12 23:11:16 +00002747 s->header.sh_type = SHT_PROGBITS;
2748 }
2749 }
2750}
2751
2752unsigned long obj_load_size(struct obj_file *f)
2753{
2754 unsigned long dot = 0;
2755 struct obj_section *sec;
2756
2757 /* Finalize the positions of the sections relative to one another. */
2758
2759 for (sec = f->load_order; sec; sec = sec->load_next) {
2760 ElfW(Addr) align;
2761
2762 align = sec->header.sh_addralign;
2763 if (align && (dot & (align - 1)))
2764 dot = (dot | (align - 1)) + 1;
2765
2766 sec->header.sh_addr = dot;
2767 dot += sec->header.sh_size;
2768 }
2769
2770 return dot;
2771}
2772
2773int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2774{
2775 int i, n = f->header.e_shnum;
2776 int ret = 1;
2777
2778 /* Finalize the addresses of the sections. */
2779
2780 f->baseaddr = base;
2781 for (i = 0; i < n; ++i)
2782 f->sections[i]->header.sh_addr += base;
2783
2784 /* And iterate over all of the relocations. */
2785
2786 for (i = 0; i < n; ++i) {
2787 struct obj_section *relsec, *symsec, *targsec, *strsec;
2788 ElfW(RelM) * rel, *relend;
2789 ElfW(Sym) * symtab;
2790 const char *strtab;
2791
2792 relsec = f->sections[i];
2793 if (relsec->header.sh_type != SHT_RELM)
2794 continue;
2795
2796 symsec = f->sections[relsec->header.sh_link];
2797 targsec = f->sections[relsec->header.sh_info];
2798 strsec = f->sections[symsec->header.sh_link];
2799
2800 rel = (ElfW(RelM) *) relsec->contents;
2801 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2802 symtab = (ElfW(Sym) *) symsec->contents;
2803 strtab = (const char *) strsec->contents;
2804
2805 for (; rel < relend; ++rel) {
2806 ElfW(Addr) value = 0;
2807 struct obj_symbol *intsym = NULL;
2808 unsigned long symndx;
2809 ElfW(Sym) * extsym = 0;
2810 const char *errmsg;
2811
2812 /* Attempt to find a value to use for this relocation. */
2813
2814 symndx = ELFW(R_SYM) (rel->r_info);
2815 if (symndx) {
2816 /* Note we've already checked for undefined symbols. */
2817
2818 extsym = &symtab[symndx];
2819 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2820 /* Local symbols we look up in the local table to be sure
2821 we get the one that is really intended. */
2822 intsym = f->local_symtab[symndx];
2823 } else {
2824 /* Others we look up in the hash table. */
2825 const char *name;
2826 if (extsym->st_name)
2827 name = strtab + extsym->st_name;
2828 else
2829 name = f->sections[extsym->st_shndx]->name;
2830 intsym = obj_find_symbol(f, name);
2831 }
2832
2833 value = obj_symbol_final_value(f, intsym);
2834 intsym->referenced = 1;
2835 }
2836#if SHT_RELM == SHT_RELA
2837#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2838 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2839 if (!extsym || !extsym->st_name ||
2840 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2841#endif
2842 value += rel->r_addend;
2843#endif
2844
2845 /* Do it! */
2846 switch (arch_apply_relocation
2847 (f, targsec, symsec, intsym, rel, value)) {
2848 case obj_reloc_ok:
2849 break;
2850
2851 case obj_reloc_overflow:
2852 errmsg = "Relocation overflow";
2853 goto bad_reloc;
2854 case obj_reloc_dangerous:
2855 errmsg = "Dangerous relocation";
2856 goto bad_reloc;
2857 case obj_reloc_unhandled:
2858 errmsg = "Unhandled relocation";
2859 bad_reloc:
2860 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002861 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002862 (long) ELFW(R_TYPE) (rel->r_info),
2863 strtab + extsym->st_name);
2864 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002865 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002866 (long) ELFW(R_TYPE) (rel->r_info));
2867 }
2868 ret = 0;
2869 break;
2870 }
2871 }
2872 }
2873
2874 /* Finally, take care of the patches. */
2875
2876 if (f->string_patches) {
2877 struct obj_string_patch *p;
2878 struct obj_section *strsec;
2879 ElfW(Addr) strsec_base;
2880 strsec = obj_find_section(f, ".kstrtab");
2881 strsec_base = strsec->header.sh_addr;
2882
2883 for (p = f->string_patches; p; p = p->next) {
2884 struct obj_section *targsec = f->sections[p->reloc_secidx];
2885 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2886 = strsec_base + p->string_offset;
2887 }
2888 }
2889
2890 if (f->symbol_patches) {
2891 struct obj_symbol_patch *p;
2892
2893 for (p = f->symbol_patches; p; p = p->next) {
2894 struct obj_section *targsec = f->sections[p->reloc_secidx];
2895 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2896 = obj_symbol_final_value(f, p->sym);
2897 }
2898 }
2899
2900 return ret;
2901}
2902
2903int obj_create_image(struct obj_file *f, char *image)
2904{
2905 struct obj_section *sec;
2906 ElfW(Addr) base = f->baseaddr;
2907
2908 for (sec = f->load_order; sec; sec = sec->load_next) {
2909 char *secimg;
2910
Eric Andersen2bf658d2001-02-24 20:01:53 +00002911 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002912 continue;
2913
2914 secimg = image + (sec->header.sh_addr - base);
2915
2916 /* Note that we allocated data for NOBITS sections earlier. */
2917 memcpy(secimg, sec->contents, sec->header.sh_size);
2918 }
2919
2920 return 1;
2921}
2922
2923/*======================================================================*/
2924
2925struct obj_file *obj_load(FILE * fp)
2926{
2927 struct obj_file *f;
2928 ElfW(Shdr) * section_headers;
2929 int shnum, i;
2930 char *shstrtab;
2931
2932 /* Read the file header. */
2933
2934 f = arch_new_file();
2935 memset(f, 0, sizeof(*f));
2936 f->symbol_cmp = strcmp;
2937 f->symbol_hash = obj_elf_hash;
2938 f->load_order_search_start = &f->load_order;
2939
2940 fseek(fp, 0, SEEK_SET);
2941 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002942 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002943 return NULL;
2944 }
2945
2946 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2947 || f->header.e_ident[EI_MAG1] != ELFMAG1
2948 || f->header.e_ident[EI_MAG2] != ELFMAG2
2949 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002950 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002951 return NULL;
2952 }
2953 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2954 || f->header.e_ident[EI_DATA] != ELFDATAM
2955 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2956 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002957 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 return NULL;
2959 }
2960 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002961 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002962 return NULL;
2963 }
2964
2965 /* Read the section headers. */
2966
2967 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002968 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00002969 (unsigned long) f->header.e_shentsize,
2970 (unsigned long) sizeof(ElfW(Shdr)));
2971 return NULL;
2972 }
2973
2974 shnum = f->header.e_shnum;
2975 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2976 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2977
2978 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2979 fseek(fp, f->header.e_shoff, SEEK_SET);
2980 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002981 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002982 return NULL;
2983 }
2984
2985 /* Read the section data. */
2986
2987 for (i = 0; i < shnum; ++i) {
2988 struct obj_section *sec;
2989
2990 f->sections[i] = sec = arch_new_section();
2991 memset(sec, 0, sizeof(*sec));
2992
2993 sec->header = section_headers[i];
2994 sec->idx = i;
2995
Eric Andersen2bf658d2001-02-24 20:01:53 +00002996 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002997 case SHT_NULL:
2998 case SHT_NOTE:
2999 case SHT_NOBITS:
3000 /* ignore */
3001 break;
3002
3003 case SHT_PROGBITS:
3004 case SHT_SYMTAB:
3005 case SHT_STRTAB:
3006 case SHT_RELM:
3007 if (sec->header.sh_size > 0) {
3008 sec->contents = xmalloc(sec->header.sh_size);
3009 fseek(fp, sec->header.sh_offset, SEEK_SET);
3010 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003011 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003012 return NULL;
3013 }
3014 } else {
3015 sec->contents = NULL;
3016 }
3017 break;
3018
3019#if SHT_RELM == SHT_REL
3020 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003021 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003022 return NULL;
3023#else
3024 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003025 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003026 return NULL;
3027#endif
3028
3029 default:
3030 if (sec->header.sh_type >= SHT_LOPROC) {
3031 /* Assume processor specific section types are debug
3032 info and can safely be ignored. If this is ever not
3033 the case (Hello MIPS?), don't put ifdefs here but
3034 create an arch_load_proc_section(). */
3035 break;
3036 }
3037
Matt Kraaidd19c692001-01-31 19:00:21 +00003038 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003039 (long) sec->header.sh_type);
3040 return NULL;
3041 }
3042 }
3043
3044 /* Do what sort of interpretation as needed by each section. */
3045
3046 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3047
3048 for (i = 0; i < shnum; ++i) {
3049 struct obj_section *sec = f->sections[i];
3050 sec->name = shstrtab + sec->header.sh_name;
3051 }
3052
3053 for (i = 0; i < shnum; ++i) {
3054 struct obj_section *sec = f->sections[i];
3055
3056 if (sec->header.sh_flags & SHF_ALLOC)
3057 obj_insert_section_load_order(f, sec);
3058
3059 switch (sec->header.sh_type) {
3060 case SHT_SYMTAB:
3061 {
3062 unsigned long nsym, j;
3063 char *strtab;
3064 ElfW(Sym) * sym;
3065
3066 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003067 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003068 (unsigned long) sec->header.sh_entsize,
3069 (unsigned long) sizeof(ElfW(Sym)));
3070 return NULL;
3071 }
3072
3073 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3074 strtab = f->sections[sec->header.sh_link]->contents;
3075 sym = (ElfW(Sym) *) sec->contents;
3076
3077 /* Allocate space for a table of local symbols. */
3078 j = f->local_symtab_size = sec->header.sh_info;
3079 f->local_symtab = xmalloc(j *=
3080 sizeof(struct obj_symbol *));
3081 memset(f->local_symtab, 0, j);
3082
3083 /* Insert all symbols into the hash table. */
3084 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3085 const char *name;
3086 if (sym->st_name)
3087 name = strtab + sym->st_name;
3088 else
3089 name = f->sections[sym->st_shndx]->name;
3090
3091 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3092 sym->st_value, sym->st_size);
3093 }
3094 }
3095 break;
3096
3097 case SHT_RELM:
3098 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003099 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003100 (unsigned long) sec->header.sh_entsize,
3101 (unsigned long) sizeof(ElfW(RelM)));
3102 return NULL;
3103 }
3104 break;
3105 }
3106 }
3107
3108 return f;
3109}
3110
3111static void hide_special_symbols(struct obj_file *f)
3112{
3113 static const char *const specials[] = {
3114 "cleanup_module",
3115 "init_module",
3116 "kernel_version",
3117 NULL
3118 };
3119
3120 struct obj_symbol *sym;
3121 const char *const *p;
3122
3123 for (p = specials; *p; ++p)
3124 if ((sym = obj_find_symbol(f, *p)) != NULL)
3125 sym->info =
3126 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3127}
3128
3129
3130
3131extern int insmod_main( int argc, char **argv)
3132{
Eric Andersena18aaf12001-01-24 19:07:09 +00003133 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003134 int k_crcs;
3135 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003136 int len;
3137 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003138 unsigned long m_size;
3139 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003140 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003141 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003142 struct stat st;
Eric Andersen9f16d612000-06-12 23:11:16 +00003143 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003144 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003145 int m_has_modinfo;
3146#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3147 int k_version;
3148 char k_strversion[STRVERSIONLEN];
3149 char m_strversion[STRVERSIONLEN];
3150 int m_version;
3151 int m_crcs;
3152#endif
3153
Erik Andersene49d5ec2000-02-08 19:58:47 +00003154 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003155 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003156 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003157 case 'f': /* force loading */
3158 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003159 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003160 case 'k': /* module loaded by kerneld, auto-cleanable */
3161 flag_autoclean = 1;
3162 break;
3163 case 'v': /* verbose output */
3164 flag_verbose = 1;
3165 break;
3166 case 'x': /* do not export externs */
3167 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003168 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003169 case 'o': /* name the output module */
3170 strncpy(m_name, optarg, BUFSIZ);
3171 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003172 case 'L': /* Stub warning */
3173 /* This is needed for compatibility with modprobe.
3174 * In theory, this does locking, but we don't do
3175 * that. So be careful and plan your life around not
3176 * loading the same module 50 times concurrently. */
3177 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003178 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003179 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003180 }
Erik Andersend387d011999-12-21 02:55:11 +00003181 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003182
3183 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003184 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003185 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003186
Erik Andersene49d5ec2000-02-08 19:58:47 +00003187 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003188 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003189 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003190 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003191 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003192 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003193 len = strlen(tmp);
3194
3195 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3196 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00003197 strncpy(m_fullName, tmp, len);
Eric Andersen114ad9c2001-01-26 01:52:14 +00003198 if (*m_name == '\0') {
3199 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003200 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003201 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003202
3203 /* Get a filedesc for the module */
Eric Andersen02b9f422001-02-15 19:07:43 +00003204 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3205 (fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003206 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00003207 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003208 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003209 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003210 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00003211 || ((fp = fopen(m_filename, "r")) == NULL))
3212 {
Matt Kraaidd19c692001-01-31 19:00:21 +00003213 error_msg("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00003214 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003215 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00003216 } else
Matt Kraaidd19c692001-01-31 19:00:21 +00003217 error_msg_and_die("No module named '%s' found in '%s'", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003218 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00003219 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00003220
3221
Matt Kraaia9819b22000-12-22 01:48:07 +00003222 if ((f = obj_load(fp)) == NULL)
3223 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003224
Eric Andersen9f16d612000-06-12 23:11:16 +00003225 if (get_modinfo_value(f, "kernel_version") == NULL)
3226 m_has_modinfo = 0;
3227 else
3228 m_has_modinfo = 1;
3229
3230#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3231 /* Version correspondence? */
3232
3233 k_version = get_kernel_version(k_strversion);
3234 if (m_has_modinfo) {
3235 m_version = new_get_module_version(f, m_strversion);
3236 } else {
3237 m_version = old_get_module_version(f, m_strversion);
3238 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003239 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003240 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003241 goto out;
3242 }
3243 }
3244
3245 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3246 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003247 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003248 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003249 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 m_filename, m_strversion, k_strversion);
3251 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003252 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003253 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003254 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003255 m_filename, m_strversion, k_strversion);
3256 goto out;
3257 }
3258 }
3259 k_crcs = 0;
3260#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3261
3262 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3263
3264 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003265#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003266 if (!new_get_kernel_symbols())
3267 goto out;
3268 k_crcs = new_is_kernel_checksummed();
3269#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003270 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003271 goto out;
3272#endif
3273 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003274#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003275 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003276 goto out;
3277 k_crcs = old_is_kernel_checksummed();
3278#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003279 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003280 goto out;
3281#endif
3282 }
3283
3284#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3285 if (m_has_modinfo)
3286 m_crcs = new_is_module_checksummed(f);
3287 else
3288 m_crcs = old_is_module_checksummed(f);
3289
3290 if (m_crcs != k_crcs)
3291 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3292#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3293
Erik Andersene49d5ec2000-02-08 19:58:47 +00003294 /* Let the module know about the kernel symbols. */
3295 add_kernel_symbols(f);
3296
Eric Andersen9f16d612000-06-12 23:11:16 +00003297 /* Allocate common symbols, symbol tables, and string tables. */
3298
3299 if (k_new_syscalls
3300 ? !new_create_this_module(f, m_name)
3301 : !old_create_mod_use_count(f))
3302 {
3303 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003304 }
3305
Eric Andersen9f16d612000-06-12 23:11:16 +00003306 if (!obj_check_undefineds(f)) {
3307 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003308 }
3309 obj_allocate_commons(f);
3310
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003311 /* done with the module name, on to the optional var=value arguments */
3312 ++optind;
3313
Eric Andersen9f16d612000-06-12 23:11:16 +00003314 if (optind < argc) {
3315 if (m_has_modinfo
3316 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3317 : !old_process_module_arguments(f, argc - optind, argv + optind))
3318 {
3319 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003320 }
3321 }
3322
Eric Andersen9f16d612000-06-12 23:11:16 +00003323 arch_create_got(f);
3324 hide_special_symbols(f);
3325
3326 if (k_new_syscalls)
3327 new_create_module_ksymtab(f);
3328
Erik Andersene49d5ec2000-02-08 19:58:47 +00003329 /* Find current size of the module */
3330 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003331
3332
Erik Andersene49d5ec2000-02-08 19:58:47 +00003333 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003334 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003335 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003336 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003337 goto out;
3338 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003339 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003340 m_size);
3341 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003342 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003343 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003344 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003345 }
Erik Andersend387d011999-12-21 02:55:11 +00003346
Eric Andersen9f16d612000-06-12 23:11:16 +00003347 if (!obj_relocate(f, m_addr)) {
3348 delete_module(m_name);
3349 goto out;
3350 }
Erik Andersend387d011999-12-21 02:55:11 +00003351
Eric Andersen9f16d612000-06-12 23:11:16 +00003352 if (k_new_syscalls
3353 ? !new_init_module(m_name, f, m_size)
3354 : !old_init_module(m_name, f, m_size))
3355 {
3356 delete_module(m_name);
3357 goto out;
3358 }
3359
Matt Kraai3e856ce2000-12-01 02:55:13 +00003360 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003361
3362out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003363 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003364 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003365}