blob: 136f9f06205208af3a36eb700e985e95e31a55c1 [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 *
Erik Andersen61677fe2000-04-13 01:18:56 +00005 * Copyright (C) 1999,2000 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
10 * and (theoretically) SH3. Note that there is still no true
11 * multiple architecture support. You just get SH3|SH4|i386, despite
12 * the mention of ARM and m68k--which may or may not work (but
13 * almost certainly do not, due to at least MATCH_MACHINE). I have
14 * only tested SH4 in little endian mode.
15 *
Eric Andersen9f16d612000-06-12 23:11:16 +000016 * Based almost entirely on the Linux modutils-2.3.11 implementation.
17 * Copyright 1996, 1997 Linux International.
18 * New implementation contributed by Richard Henderson <rth@tamu.edu>
19 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
20 * Restructured (and partly rewritten) by:
21 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000022 *
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 * General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 *
37 */
38
39#include "internal.h"
40#include <stdlib.h>
41#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000042#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000043#include <errno.h>
44#include <unistd.h>
45#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000046#include <ctype.h>
47#include <assert.h>
Eric Andersen999bf722000-07-09 06:59:58 +000048#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000049#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000050
51//----------------------------------------------------------------------------
52//--------modutils module.h, lines 45-242
53//----------------------------------------------------------------------------
54
55/* Definitions for the Linux module syscall interface.
56 Copyright 1996, 1997 Linux International.
57
58 Contributed by Richard Henderson <rth@tamu.edu>
59
60 This file is part of the Linux modutils.
61
62 This program is free software; you can redistribute it and/or modify it
63 under the terms of the GNU General Public License as published by the
64 Free Software Foundation; either version 2 of the License, or (at your
65 option) any later version.
66
67 This program is distributed in the hope that it will be useful, but
68 WITHOUT ANY WARRANTY; without even the implied warranty of
69 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
70 General Public License for more details.
71
72 You should have received a copy of the GNU General Public License
73 along with this program; if not, write to the Free Software Foundation,
74 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
75
76
77#ifndef MODUTILS_MODULE_H
78#define MODUTILS_MODULE_H 1
79
Eric Andersenfe4208f2000-09-24 03:44:29 +000080#ident "$Id: insmod.c,v 1.24 2000/09/24 03:44:29 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +000081
82/* This file contains the structures used by the 2.0 and 2.1 kernels.
83 We do not use the kernel headers directly because we do not wish
84 to be dependant on a particular kernel version to compile insmod. */
85
86
87/*======================================================================*/
88/* The structures used by Linux 2.0. */
89
90/* The symbol format used by get_kernel_syms(2). */
91struct old_kernel_sym
92{
93 unsigned long value;
94 char name[60];
95};
96
97struct old_module_ref
98{
99 unsigned long module; /* kernel addresses */
100 unsigned long next;
101};
102
103struct old_module_symbol
104{
105 unsigned long addr;
106 unsigned long name;
107};
108
109struct old_symbol_table
110{
111 int size; /* total, including string table!!! */
112 int n_symbols;
113 int n_refs;
114 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
115 struct old_module_ref ref[0]; /* actual size defined by n_refs */
116};
117
118struct old_mod_routines
119{
120 unsigned long init;
121 unsigned long cleanup;
122};
123
124struct old_module
125{
126 unsigned long next;
127 unsigned long ref; /* the list of modules that refer to me */
128 unsigned long symtab;
129 unsigned long name;
130 int size; /* size of module in pages */
131 unsigned long addr; /* address of module */
132 int state;
133 unsigned long cleanup; /* cleanup routine */
134};
135
136/* Sent to init_module(2) or'ed into the code size parameter. */
137#define OLD_MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */
138
139int get_kernel_syms(struct old_kernel_sym *);
140int old_sys_init_module(const char *name, char *code, unsigned codesize,
141 struct old_mod_routines *, struct old_symbol_table *);
142
143/*======================================================================*/
144/* For sizeof() which are related to the module platform and not to the
145 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
146
147#define tgt_sizeof_char sizeof(char)
148#define tgt_sizeof_short sizeof(short)
149#define tgt_sizeof_int sizeof(int)
150#define tgt_sizeof_long sizeof(long)
151#define tgt_sizeof_char_p sizeof(char *)
152#define tgt_sizeof_void_p sizeof(void *)
153#define tgt_long long
154
155#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
156#undef tgt_sizeof_long
157#undef tgt_sizeof_char_p
158#undef tgt_sizeof_void_p
159#undef tgt_long
160#define tgt_sizeof_long 8
161#define tgt_sizeof_char_p 8
162#define tgt_sizeof_void_p 8
163#define tgt_long long long
164#endif
165
166/*======================================================================*/
167/* The structures used in Linux 2.1. */
168
169/* Note: new_module_symbol does not use tgt_long intentionally */
170struct new_module_symbol
171{
172 unsigned long value;
173 unsigned long name;
174};
175
176struct new_module_persist;
177
178struct new_module_ref
179{
180 unsigned tgt_long dep; /* kernel addresses */
181 unsigned tgt_long ref;
182 unsigned tgt_long next_ref;
183};
184
185struct new_module
186{
187 unsigned tgt_long size_of_struct; /* == sizeof(module) */
188 unsigned tgt_long next;
189 unsigned tgt_long name;
190 unsigned tgt_long size;
191
192 tgt_long usecount;
193 unsigned tgt_long flags; /* AUTOCLEAN et al */
194
195 unsigned nsyms;
196 unsigned ndeps;
197
198 unsigned tgt_long syms;
199 unsigned tgt_long deps;
200 unsigned tgt_long refs;
201 unsigned tgt_long init;
202 unsigned tgt_long cleanup;
203 unsigned tgt_long ex_table_start;
204 unsigned tgt_long ex_table_end;
205#ifdef __alpha__
206 unsigned tgt_long gp;
207#endif
208 /* Everything after here is extension. */
209 unsigned tgt_long persist_start;
210 unsigned tgt_long persist_end;
211 unsigned tgt_long can_unload;
212 unsigned tgt_long runsize;
213};
214
215struct new_module_info
216{
217 unsigned long addr;
218 unsigned long size;
219 unsigned long flags;
220 long usecount;
221};
222
223/* Bits of module.flags. */
224#define NEW_MOD_RUNNING 1
225#define NEW_MOD_DELETED 2
226#define NEW_MOD_AUTOCLEAN 4
227#define NEW_MOD_VISITED 8
228#define NEW_MOD_USED_ONCE 16
229
230int new_sys_init_module(const char *name, const struct new_module *);
231int query_module(const char *name, int which, void *buf, size_t bufsize,
232 size_t *ret);
233
234/* Values for query_module's which. */
235
236#define QM_MODULES 1
237#define QM_DEPS 2
238#define QM_REFS 3
239#define QM_SYMBOLS 4
240#define QM_INFO 5
241
242/*======================================================================*/
243/* The system calls unchanged between 2.0 and 2.1. */
244
245unsigned long create_module(const char *, size_t);
246int delete_module(const char *);
247
248
249#endif /* module.h */
250
251//----------------------------------------------------------------------------
252//--------end of modutils module.h
253//----------------------------------------------------------------------------
254
255
256
257//----------------------------------------------------------------------------
258//--------modutils obj.h, lines 253-462
259//----------------------------------------------------------------------------
260
261/* Elf object file loading and relocation routines.
262 Copyright 1996, 1997 Linux International.
263
264 Contributed by Richard Henderson <rth@tamu.edu>
265
266 This file is part of the Linux modutils.
267
268 This program is free software; you can redistribute it and/or modify it
269 under the terms of the GNU General Public License as published by the
270 Free Software Foundation; either version 2 of the License, or (at your
271 option) any later version.
272
273 This program is distributed in the hope that it will be useful, but
274 WITHOUT ANY WARRANTY; without even the implied warranty of
275 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
276 General Public License for more details.
277
278 You should have received a copy of the GNU General Public License
279 along with this program; if not, write to the Free Software Foundation,
280 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
281
282
283#ifndef MODUTILS_OBJ_H
284#define MODUTILS_OBJ_H 1
285
Eric Andersenfe4208f2000-09-24 03:44:29 +0000286#ident "$Id: insmod.c,v 1.24 2000/09/24 03:44:29 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000287
288/* The relocatable object is manipulated using elfin types. */
289
290#include <stdio.h>
291#include <elf.h>
292
293
294/* Machine-specific elf macros for i386 et al. */
295
Eric Andersenfe4208f2000-09-24 03:44:29 +0000296/* the SH changes have only been tested on the SH4 in =little endian= mode */
297/* I'm not sure about big endian, so let's warn: */
298
299#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
300#error insmod.c may require changes for use on big endian SH4/SH3
301#endif
302
303/* it may or may not work on the SH1/SH2... So let's error on those
304 also */
305#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
306#error insmod.c may require changes for non-SH3/SH4 use
307#endif
308
Eric Andersen9f16d612000-06-12 23:11:16 +0000309#define ELFCLASSM ELFCLASS32
310#define ELFDATAM ELFDATA2LSB
311
Eric Andersen9f16d612000-06-12 23:11:16 +0000312
Eric Andersenfe4208f2000-09-24 03:44:29 +0000313
314#if defined(__sh__)
315
316#define MATCH_MACHINE(x) (x == EM_SH)
317#define SHT_RELM SHT_RELA
318#define Elf32_RelM Elf32_Rela
319
320#else
321
322/* presumably we can use these for anything but the SH */
323/* this is the previous behavior, but it does result in
324 insmod.c being broken on anything except i386 */
325
326#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Eric Andersen9f16d612000-06-12 23:11:16 +0000327#define SHT_RELM SHT_REL
328#define Elf32_RelM Elf32_Rel
329
Eric Andersenfe4208f2000-09-24 03:44:29 +0000330#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000331
332#ifndef ElfW
333# if ELFCLASSM == ELFCLASS32
334# define ElfW(x) Elf32_ ## x
335# define ELFW(x) ELF32_ ## x
336# else
337# define ElfW(x) Elf64_ ## x
338# define ELFW(x) ELF64_ ## x
339# endif
340#endif
341
342/* For some reason this is missing from libc5. */
343#ifndef ELF32_ST_INFO
344# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
345#endif
346
347#ifndef ELF64_ST_INFO
348# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
349#endif
350
351struct obj_string_patch;
352struct obj_symbol_patch;
353
354struct obj_section
355{
356 ElfW(Shdr) header;
357 const char *name;
358 char *contents;
359 struct obj_section *load_next;
360 int idx;
361};
362
363struct obj_symbol
364{
365 struct obj_symbol *next; /* hash table link */
366 const char *name;
367 unsigned long value;
368 unsigned long size;
369 int secidx; /* the defining section index/module */
370 int info;
371 int ksymidx; /* for export to the kernel symtab */
372 int referenced; /* actually used in the link */
373};
374
375/* Hardcode the hash table size. We shouldn't be needing so many
376 symbols that we begin to degrade performance, and we get a big win
377 by giving the compiler a constant divisor. */
378
379#define HASH_BUCKETS 521
380
381struct obj_file
382{
383 ElfW(Ehdr) header;
384 ElfW(Addr) baseaddr;
385 struct obj_section **sections;
386 struct obj_section *load_order;
387 struct obj_section **load_order_search_start;
388 struct obj_string_patch *string_patches;
389 struct obj_symbol_patch *symbol_patches;
390 int (*symbol_cmp)(const char *, const char *);
391 unsigned long (*symbol_hash)(const char *);
392 unsigned long local_symtab_size;
393 struct obj_symbol **local_symtab;
394 struct obj_symbol *symtab[HASH_BUCKETS];
395};
396
397enum obj_reloc
398{
399 obj_reloc_ok,
400 obj_reloc_overflow,
401 obj_reloc_dangerous,
402 obj_reloc_unhandled
403};
404
405struct obj_string_patch
406{
407 struct obj_string_patch *next;
408 int reloc_secidx;
409 ElfW(Addr) reloc_offset;
410 ElfW(Addr) string_offset;
411};
412
413struct obj_symbol_patch
414{
415 struct obj_symbol_patch *next;
416 int reloc_secidx;
417 ElfW(Addr) reloc_offset;
418 struct obj_symbol *sym;
419};
420
421
422/* Generic object manipulation routines. */
423
424unsigned long obj_elf_hash(const char *);
425
426unsigned long obj_elf_hash_n(const char *, unsigned long len);
427
428struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
429 unsigned long symidx, int info, int secidx,
430 ElfW(Addr) value, unsigned long size);
431
432struct obj_symbol *obj_find_symbol (struct obj_file *f,
433 const char *name);
434
435ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
436 struct obj_symbol *sym);
437
438void obj_set_symbol_compare(struct obj_file *f,
439 int (*cmp)(const char *, const char *),
440 unsigned long (*hash)(const char *));
441
442struct obj_section *obj_find_section (struct obj_file *f,
443 const char *name);
444
445void obj_insert_section_load_order (struct obj_file *f,
446 struct obj_section *sec);
447
448struct obj_section *obj_create_alloced_section (struct obj_file *f,
449 const char *name,
450 unsigned long align,
451 unsigned long size);
452
453struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
454 const char *name,
455 unsigned long align,
456 unsigned long size);
457
458void *obj_extend_section (struct obj_section *sec, unsigned long more);
459
460int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
461 const char *string);
462
463int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
464 struct obj_symbol *sym);
465
466int obj_check_undefineds(struct obj_file *f);
467
468void obj_allocate_commons(struct obj_file *f);
469
470unsigned long obj_load_size (struct obj_file *f);
471
472int obj_relocate (struct obj_file *f, ElfW(Addr) base);
473
474struct obj_file *obj_load(FILE *f);
475
476int obj_create_image (struct obj_file *f, char *image);
477
478/* Architecture specific manipulation routines. */
479
480struct obj_file *arch_new_file (void);
481
482struct obj_section *arch_new_section (void);
483
484struct obj_symbol *arch_new_symbol (void);
485
486enum obj_reloc arch_apply_relocation (struct obj_file *f,
487 struct obj_section *targsec,
488 struct obj_section *symsec,
489 struct obj_symbol *sym,
490 ElfW(RelM) *rel, ElfW(Addr) value);
491
492int arch_create_got (struct obj_file *f);
493
494struct new_module;
495int arch_init_module (struct obj_file *f, struct new_module *);
496
497#endif /* obj.h */
498//----------------------------------------------------------------------------
499//--------end of modutils obj.h
500//----------------------------------------------------------------------------
501
502
503
504
Erik Andersen02104321999-12-17 18:57:34 +0000505
Erik Andersend387d011999-12-21 02:55:11 +0000506#define _PATH_MODULES "/lib/modules"
Eric Andersen9f16d612000-06-12 23:11:16 +0000507#define STRVERSIONLEN 32
Erik Andersend387d011999-12-21 02:55:11 +0000508
Eric Andersen9f16d612000-06-12 23:11:16 +0000509#if !defined(BB_FEATURE_INSMOD_NEW_KERNEL) && !defined(BB_FEATURE_INSMOD_OLD_KERNEL)
510#error "Must have ether BB_FEATURE_INSMOD_NEW_KERNEL or BB_FEATURE_INSMOD_OLD_KERNEL defined"
511#endif
512
513/*======================================================================*/
514
515int flag_force_load = 0;
516int flag_autoclean = 0;
517int flag_verbose = 0;
518int flag_export = 1;
519
520
521/*======================================================================*/
522
Eric Andersenfe4208f2000-09-24 03:44:29 +0000523/* previously, these were named i386_* but since we could be
524 compiling for the sh, I've renamed them to the more general
525 arch_* These structures are the same between the x86 and SH,
526 and we can't support anything else right now anyway. In the
527 future maybe they should be #if defined'd */
528
529struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000530 int offset;
531 unsigned offset_done:1;
532 unsigned reloc_done:1;
533};
534
Eric Andersenfe4208f2000-09-24 03:44:29 +0000535struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000536 struct obj_file root;
537 struct obj_section *got;
538};
539
Eric Andersenfe4208f2000-09-24 03:44:29 +0000540struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000541 struct obj_symbol root;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000542 struct arch_got_entry gotent;
Eric Andersen9f16d612000-06-12 23:11:16 +0000543};
544
545
Eric Andersen9f16d612000-06-12 23:11:16 +0000546struct external_module {
547 const char *name;
548 ElfW(Addr) addr;
549 int used;
550 size_t nsyms;
551 struct new_module_symbol *syms;
552};
553
554struct new_module_symbol *ksyms;
555size_t nksyms;
556
557struct external_module *ext_modules;
558int n_ext_modules;
559int n_ext_modules_used;
560
Erik Andersend387d011999-12-21 02:55:11 +0000561
562
Erik Andersen02104321999-12-17 18:57:34 +0000563/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000564#define __NR_new_sys_init_module __NR_init_module
565_syscall2(int, new_sys_init_module, const char *, name,
566 const struct new_module *, info)
567#define __NR_old_sys_init_module __NR_init_module
568_syscall5(int, old_sys_init_module, const char *, name, char *, code,
569 unsigned, codesize, struct old_mod_routines *, routines,
570 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000571#ifndef BB_RMMOD
572_syscall1(int, delete_module, const char *, name)
573#else
574extern int delete_module(const char *);
575#endif
576
Eric Andersenfe4208f2000-09-24 03:44:29 +0000577/* This is kind of troublesome. See, we don't actually support
578 the m68k or the arm the same way we support i386 and (now)
579 sh. In doing my SH patch, I just assumed that whatever works
580 for i386 also works for m68k and arm since currently insmod.c
581 does nothing special for them. If this isn't true, the below
582 line is rather misleading IMHO, and someone should either
583 change it or add more proper architecture-dependent support
584 for these boys.
585
586 -- Bryan Rittmeyer <bryan@ixiacom.com> */
587
Erik Andersen02104321999-12-17 18:57:34 +0000588#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
589/* Jump through hoops to fixup error return codes */
590#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000591static inline _syscall2(long, _create_module, const char *, name, size_t,
592 size)
Erik Andersen02104321999-12-17 18:57:34 +0000593unsigned long create_module(const char *name, size_t size)
594{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000595 long ret = _create_module(name, size);
596
597 if (ret == -1 && errno > 125) {
598 ret = -errno;
599 errno = 0;
600 }
601 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000602}
603#else
604_syscall2(unsigned long, create_module, const char *, name, size_t, size)
605#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000606static char m_filename[BUFSIZ + 1] = "\0";
607static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000608
Eric Andersen9f16d612000-06-12 23:11:16 +0000609/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000610
Eric Andersen9f16d612000-06-12 23:11:16 +0000611
612static int findNamedModule(const char *fileName, struct stat *statbuf,
613 void *userDate)
614{
615 char *fullName = (char *) userDate;
616
617
618 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000619 return (FALSE);
620 else {
621 char *tmp = strrchr(fileName, '/');
622
623 if (tmp == NULL)
624 tmp = (char *) fileName;
625 else
626 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000628 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000629 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000630 return (FALSE);
631 }
Erik Andersend387d011999-12-21 02:55:11 +0000632 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000633 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000634}
635
Erik Andersen02104321999-12-17 18:57:34 +0000636
Eric Andersen9f16d612000-06-12 23:11:16 +0000637/*======================================================================*/
638
639struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000640{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000641 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000642 f = xmalloc(sizeof(*f));
643 f->got = NULL;
644 return &f->root;
645}
646
647struct obj_section *arch_new_section(void)
648{
649 return xmalloc(sizeof(struct obj_section));
650}
651
652struct obj_symbol *arch_new_symbol(void)
653{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000654 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000655 sym = xmalloc(sizeof(*sym));
656 memset(&sym->gotent, 0, sizeof(sym->gotent));
657 return &sym->root;
658}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000659
Eric Andersen9f16d612000-06-12 23:11:16 +0000660enum obj_reloc
661arch_apply_relocation(struct obj_file *f,
662 struct obj_section *targsec,
663 struct obj_section *symsec,
664 struct obj_symbol *sym,
Eric Andersenfe4208f2000-09-24 03:44:29 +0000665#if defined(__sh__)
666 Elf32_Rela * rel, Elf32_Addr v)
667#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000668 Elf32_Rel * rel, Elf32_Addr v)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000669#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000670{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000671 struct arch_file *ifile = (struct arch_file *) f;
672 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000673
674 Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset);
675 Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
676 Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
677
678 enum obj_reloc ret = obj_reloc_ok;
679
680 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000681
682/* even though these constants seem to be the same for
683 the i386 and the sh, we "#if define" them for clarity
684 and in case that ever changes */
685#if defined(__sh__)
686 case R_SH_NONE:
687#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000688 case R_386_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000689#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000690 break;
691
Eric Andersenfe4208f2000-09-24 03:44:29 +0000692#if defined(__sh__)
693 case R_SH_DIR32:
694#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000695 case R_386_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000696#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000697 *loc += v;
698 break;
699
Eric Andersenfe4208f2000-09-24 03:44:29 +0000700#if defined(__sh__)
701 case R_SH_REL32:
702#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000703 case R_386_PLT32:
704 case R_386_PC32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000705#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000706 *loc += v - dot;
707 break;
708
Eric Andersenfe4208f2000-09-24 03:44:29 +0000709#if defined(__sh__)
710 case R_SH_PLT32:
711 *loc = v - dot;
712 break;
713#endif
714
715
716#if defined(__sh__)
717 case R_SH_GLOB_DAT:
718 case R_SH_JMP_SLOT:
719 *loc = v;
720 break;
721#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000722 case R_386_GLOB_DAT:
723 case R_386_JMP_SLOT:
724 *loc = v;
725 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000726#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000727
Eric Andersenfe4208f2000-09-24 03:44:29 +0000728#if defined(__sh__)
729 case R_SH_RELATIVE:
730 *loc += f->baseaddr + rel->r_addend;
731 break;
732#else
733 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000734 *loc += f->baseaddr;
735 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000736#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000737
Eric Andersenfe4208f2000-09-24 03:44:29 +0000738#if defined(__sh__)
739 case R_SH_GOTPC:
740 assert(got != 0);
741 *loc += got - dot + rel->r_addend;;
742 break;
743#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000744 case R_386_GOTPC:
745 assert(got != 0);
746 *loc += got - dot;
747 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000748#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000749
Eric Andersenfe4208f2000-09-24 03:44:29 +0000750#if defined(__sh__)
751 case R_SH_GOT32:
752 assert(isym != NULL);
753 if (!isym->gotent.reloc_done) {
754 isym->gotent.reloc_done = 1;
755 *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
756 v;
757 }
758 *loc += isym->gotent.offset + rel->r_addend;
759 break;
760#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000761 case R_386_GOT32:
762 assert(isym != NULL);
763 if (!isym->gotent.reloc_done) {
764 isym->gotent.reloc_done = 1;
765 *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
766 v;
767 }
768 *loc += isym->gotent.offset;
769 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000770#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000771
Eric Andersenfe4208f2000-09-24 03:44:29 +0000772#if defined(__sh__)
773 case R_SH_GOTOFF:
774#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000775 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000776#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000777 assert(got != 0);
778 *loc += v - got;
779 break;
780
781 default:
782 ret = obj_reloc_unhandled;
783 break;
784 }
785
786 return ret;
787}
788
789int arch_create_got(struct obj_file *f)
790{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000791 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000792 int i, n, offset = 0, gotneeded = 0;
793
794 n = ifile->root.header.e_shnum;
795 for (i = 0; i < n; ++i) {
796 struct obj_section *relsec, *symsec, *strsec;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000797#if defined(__sh__)
798 Elf32_Rela *rel, *relend;
799#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000800 Elf32_Rel *rel, *relend;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000801#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000802 Elf32_Sym *symtab;
803 const char *strtab;
804
805 relsec = ifile->root.sections[i];
806 if (relsec->header.sh_type != SHT_REL)
807 continue;
808
809 symsec = ifile->root.sections[relsec->header.sh_link];
810 strsec = ifile->root.sections[symsec->header.sh_link];
811
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812
813#if defined(__sh__)
814 rel = (Elf32_Rela *) relsec->contents;
815 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rela));
816#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000817 rel = (Elf32_Rel *) relsec->contents;
818 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
Eric Andersenfe4208f2000-09-24 03:44:29 +0000819#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000820 symtab = (Elf32_Sym *) symsec->contents;
821 strtab = (const char *) strsec->contents;
822
823 for (; rel < relend; ++rel) {
824 Elf32_Sym *extsym;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000826 const char *name;
827
828 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000829#if defined(__sh__)
830 case R_SH_GOTPC:
831 case R_SH_GOTOFF:
832#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 case R_386_GOTPC:
834 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000835#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000836 gotneeded = 1;
837 default:
838 continue;
839
Eric Andersenfe4208f2000-09-24 03:44:29 +0000840#if defined(__sh__)
841 case R_SH_GOT32:
842#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000843 case R_386_GOT32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000844#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 break;
846 }
847
848 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
849 if (extsym->st_name)
850 name = strtab + extsym->st_name;
851 else
852 name = f->sections[extsym->st_shndx]->name;
853 intsym =
Eric Andersenfe4208f2000-09-24 03:44:29 +0000854 (struct arch_symbol *) obj_find_symbol(&ifile->root, name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000855
856 if (!intsym->gotent.offset_done) {
857 intsym->gotent.offset_done = 1;
858 intsym->gotent.offset = offset;
859 offset += 4;
860 }
861 }
862 }
863
864 if (offset > 0 || gotneeded)
865 ifile->got =
866 obj_create_alloced_section(&ifile->root, ".got", 4, offset);
867
868 return 1;
869}
870
871int arch_init_module(struct obj_file *f, struct new_module *mod)
872{
873 return 1;
874}
875
876
877/*======================================================================*/
878
879/* Standard ELF hash function. */
880inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
881{
882 unsigned long h = 0;
883 unsigned long g;
884 unsigned char ch;
885
886 while (n > 0) {
887 ch = *name++;
888 h = (h << 4) + ch;
889 if ((g = (h & 0xf0000000)) != 0) {
890 h ^= g >> 24;
891 h &= ~g;
892 }
893 n--;
894 }
895 return h;
896}
897
898unsigned long obj_elf_hash(const char *name)
899{
900 return obj_elf_hash_n(name, strlen(name));
901}
902
903#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
904/* Get the kernel version in the canonical integer form. */
905
906static int get_kernel_version(char str[STRVERSIONLEN])
907{
908 struct utsname uts_info;
909 char *p, *q;
910 int a, b, c;
911
912 if (uname(&uts_info) < 0)
913 return -1;
914 strncpy(str, uts_info.release, STRVERSIONLEN);
915 p = uts_info.release;
916
917 a = strtoul(p, &p, 10);
918 if (*p != '.')
919 return -1;
920 b = strtoul(p + 1, &p, 10);
921 if (*p != '.')
922 return -1;
923 c = strtoul(p + 1, &q, 10);
924 if (p + 1 == q)
925 return -1;
926
927 return a << 16 | b << 8 | c;
928}
929
930/* String comparison for non-co-versioned kernel and module. */
931
932static int ncv_strcmp(const char *a, const char *b)
933{
934 size_t alen = strlen(a), blen = strlen(b);
935
936 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
937 return strncmp(a, b, alen);
938 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
939 return strncmp(a, b, blen);
940 else
941 return strcmp(a, b);
942}
943
944/* String hashing for non-co-versioned kernel and module. Here
945 we are simply forced to drop the crc from the hash. */
946
947static unsigned long ncv_symbol_hash(const char *str)
948{
949 size_t len = strlen(str);
950 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
951 len -= 10;
952 return obj_elf_hash_n(str, len);
953}
954
955void
956obj_set_symbol_compare(struct obj_file *f,
957 int (*cmp) (const char *, const char *),
958 unsigned long (*hash) (const char *))
959{
960 if (cmp)
961 f->symbol_cmp = cmp;
962 if (hash) {
963 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
964 int i;
965
966 f->symbol_hash = hash;
967
968 memcpy(tmptab, f->symtab, sizeof(tmptab));
969 memset(f->symtab, 0, sizeof(f->symtab));
970
971 for (i = 0; i < HASH_BUCKETS; ++i)
972 for (sym = tmptab[i]; sym; sym = next) {
973 unsigned long h = hash(sym->name) % HASH_BUCKETS;
974 next = sym->next;
975 sym->next = f->symtab[h];
976 f->symtab[h] = sym;
977 }
978 }
979}
980
981#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
982
983
984struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
985 unsigned long symidx, int info,
986 int secidx, ElfW(Addr) value,
987 unsigned long size)
988{
989 struct obj_symbol *sym;
990 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
991 int n_type = ELFW(ST_TYPE) (info);
992 int n_binding = ELFW(ST_BIND) (info);
993
994 for (sym = f->symtab[hash]; sym; sym = sym->next)
995 if (f->symbol_cmp(sym->name, name) == 0) {
996 int o_secidx = sym->secidx;
997 int o_info = sym->info;
998 int o_type = ELFW(ST_TYPE) (o_info);
999 int o_binding = ELFW(ST_BIND) (o_info);
1000
1001 /* A redefinition! Is it legal? */
1002
1003 if (secidx == SHN_UNDEF)
1004 return sym;
1005 else if (o_secidx == SHN_UNDEF)
1006 goto found;
1007 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1008 /* Cope with local and global symbols of the same name
1009 in the same object file, as might have been created
1010 by ld -r. The only reason locals are now seen at this
1011 level at all is so that we can do semi-sensible things
1012 with parameters. */
1013
1014 struct obj_symbol *nsym, **p;
1015
1016 nsym = arch_new_symbol();
1017 nsym->next = sym->next;
1018 nsym->ksymidx = -1;
1019
1020 /* Excise the old (local) symbol from the hash chain. */
1021 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1022 continue;
1023 *p = sym = nsym;
1024 goto found;
1025 } else if (n_binding == STB_LOCAL) {
1026 /* Another symbol of the same name has already been defined.
1027 Just add this to the local table. */
1028 sym = arch_new_symbol();
1029 sym->next = NULL;
1030 sym->ksymidx = -1;
1031 f->local_symtab[symidx] = sym;
1032 goto found;
1033 } else if (n_binding == STB_WEAK)
1034 return sym;
1035 else if (o_binding == STB_WEAK)
1036 goto found;
1037 /* Don't unify COMMON symbols with object types the programmer
1038 doesn't expect. */
1039 else if (secidx == SHN_COMMON
1040 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1041 return sym;
1042 else if (o_secidx == SHN_COMMON
1043 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1044 goto found;
1045 else {
1046 /* Don't report an error if the symbol is coming from
1047 the kernel or some external module. */
1048 if (secidx <= SHN_HIRESERVE)
Matt Kraaid537a952000-07-14 01:51:25 +00001049 errorMsg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001050 return sym;
1051 }
1052 }
1053
1054 /* Completely new symbol. */
1055 sym = arch_new_symbol();
1056 sym->next = f->symtab[hash];
1057 f->symtab[hash] = sym;
1058 sym->ksymidx = -1;
1059
1060 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1061 f->local_symtab[symidx] = sym;
1062
1063 found:
1064 sym->name = name;
1065 sym->value = value;
1066 sym->size = size;
1067 sym->secidx = secidx;
1068 sym->info = info;
1069
1070 return sym;
1071}
1072
1073struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1074{
1075 struct obj_symbol *sym;
1076 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1077
1078 for (sym = f->symtab[hash]; sym; sym = sym->next)
1079 if (f->symbol_cmp(sym->name, name) == 0)
1080 return sym;
1081
1082 return NULL;
1083}
1084
1085ElfW(Addr)
1086 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1087{
1088 if (sym) {
1089 if (sym->secidx >= SHN_LORESERVE)
1090 return sym->value;
1091
1092 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1093 } else {
1094 /* As a special case, a NULL sym has value zero. */
1095 return 0;
1096 }
1097}
1098
1099struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1100{
1101 int i, n = f->header.e_shnum;
1102
1103 for (i = 0; i < n; ++i)
1104 if (strcmp(f->sections[i]->name, name) == 0)
1105 return f->sections[i];
1106
1107 return NULL;
1108}
1109
1110static int obj_load_order_prio(struct obj_section *a)
1111{
1112 unsigned long af, ac;
1113
1114 af = a->header.sh_flags;
1115
1116 ac = 0;
1117 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1118 strcmp(a->name + 5, ".init"))
1119 ac |= 32;
1120 if (af & SHF_ALLOC)
1121 ac |= 16;
1122 if (!(af & SHF_WRITE))
1123 ac |= 8;
1124 if (af & SHF_EXECINSTR)
1125 ac |= 4;
1126 if (a->header.sh_type != SHT_NOBITS)
1127 ac |= 2;
1128
1129 return ac;
1130}
1131
1132void
1133obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1134{
1135 struct obj_section **p;
1136 int prio = obj_load_order_prio(sec);
1137 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1138 if (obj_load_order_prio(*p) < prio)
1139 break;
1140 sec->load_next = *p;
1141 *p = sec;
1142}
1143
1144struct obj_section *obj_create_alloced_section(struct obj_file *f,
1145 const char *name,
1146 unsigned long align,
1147 unsigned long size)
1148{
1149 int newidx = f->header.e_shnum++;
1150 struct obj_section *sec;
1151
1152 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1153 f->sections[newidx] = sec = arch_new_section();
1154
1155 memset(sec, 0, sizeof(*sec));
1156 sec->header.sh_type = SHT_PROGBITS;
1157 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1158 sec->header.sh_size = size;
1159 sec->header.sh_addralign = align;
1160 sec->name = name;
1161 sec->idx = newidx;
1162 if (size)
1163 sec->contents = xmalloc(size);
1164
1165 obj_insert_section_load_order(f, sec);
1166
1167 return sec;
1168}
1169
1170struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1171 const char *name,
1172 unsigned long align,
1173 unsigned long size)
1174{
1175 int newidx = f->header.e_shnum++;
1176 struct obj_section *sec;
1177
1178 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1179 f->sections[newidx] = sec = arch_new_section();
1180
1181 memset(sec, 0, sizeof(*sec));
1182 sec->header.sh_type = SHT_PROGBITS;
1183 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1184 sec->header.sh_size = size;
1185 sec->header.sh_addralign = align;
1186 sec->name = name;
1187 sec->idx = newidx;
1188 if (size)
1189 sec->contents = xmalloc(size);
1190
1191 sec->load_next = f->load_order;
1192 f->load_order = sec;
1193 if (f->load_order_search_start == &f->load_order)
1194 f->load_order_search_start = &sec->load_next;
1195
1196 return sec;
1197}
1198
1199void *obj_extend_section(struct obj_section *sec, unsigned long more)
1200{
1201 unsigned long oldsize = sec->header.sh_size;
1202 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1203 return sec->contents + oldsize;
1204}
1205
1206
1207
1208/* Conditionally add the symbols from the given symbol set to the
1209 new module. */
1210
1211static int
1212add_symbols_from(
1213 struct obj_file *f,
1214 int idx, struct new_module_symbol *syms, size_t nsyms)
1215{
1216 struct new_module_symbol *s;
1217 size_t i;
1218 int used = 0;
1219
1220 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1221
1222 /* Only add symbols that are already marked external. If we
1223 override locals we may cause problems for argument initialization.
1224 We will also create a false dependency on the module. */
1225 struct obj_symbol *sym;
1226
1227 sym = obj_find_symbol(f, (char *) s->name);
1228 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1229 sym = obj_add_symbol(f, (char *) s->name, -1,
1230 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1231 idx, s->value, 0);
1232 /* Did our symbol just get installed? If so, mark the
1233 module as "used". */
1234 if (sym->secidx == idx)
1235 used = 1;
1236 }
1237 }
1238
1239 return used;
1240}
1241
1242static void add_kernel_symbols(struct obj_file *f)
1243{
1244 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001245 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001246
1247 /* Add module symbols first. */
1248
1249 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1250 if (m->nsyms
1251 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1252 m->nsyms)) m->used = 1, ++nused;
1253
1254 n_ext_modules_used = nused;
1255
1256 /* And finally the symbols from the kernel proper. */
1257
1258 if (nksyms)
1259 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1260}
1261
1262static char *get_modinfo_value(struct obj_file *f, const char *key)
1263{
1264 struct obj_section *sec;
1265 char *p, *v, *n, *ep;
1266 size_t klen = strlen(key);
1267
1268 sec = obj_find_section(f, ".modinfo");
1269 if (sec == NULL)
1270 return NULL;
1271 p = sec->contents;
1272 ep = p + sec->header.sh_size;
1273 while (p < ep) {
1274 v = strchr(p, '=');
1275 n = strchr(p, '\0');
1276 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001277 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001278 return v + 1;
1279 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001280 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001281 return n;
1282 }
1283 p = n + 1;
1284 }
1285
1286 return NULL;
1287}
1288
1289
1290/*======================================================================*/
1291/* Functions relating to module loading in pre 2.1 kernels. */
1292
1293static int
1294old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1295{
1296 while (argc > 0) {
1297 char *p, *q;
1298 struct obj_symbol *sym;
1299 int *loc;
1300
1301 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001302 if ((q = strchr(p, '=')) == NULL) {
1303 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001304 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001305 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001306 *q++ = '\0';
1307
1308 sym = obj_find_symbol(f, p);
1309
1310 /* Also check that the parameter was not resolved from the kernel. */
1311 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001312 errorMsg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001313 return 0;
1314 }
1315
1316 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1317
1318 /* Do C quoting if we begin with a ". */
1319 if (*q == '"') {
1320 char *r, *str;
1321
1322 str = alloca(strlen(q));
1323 for (r = str, q++; *q != '"'; ++q, ++r) {
1324 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001325 errorMsg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001326 return 0;
1327 } else if (*q == '\\')
1328 switch (*++q) {
1329 case 'a':
1330 *r = '\a';
1331 break;
1332 case 'b':
1333 *r = '\b';
1334 break;
1335 case 'e':
1336 *r = '\033';
1337 break;
1338 case 'f':
1339 *r = '\f';
1340 break;
1341 case 'n':
1342 *r = '\n';
1343 break;
1344 case 'r':
1345 *r = '\r';
1346 break;
1347 case 't':
1348 *r = '\t';
1349 break;
1350
1351 case '0':
1352 case '1':
1353 case '2':
1354 case '3':
1355 case '4':
1356 case '5':
1357 case '6':
1358 case '7':
1359 {
1360 int c = *q - '0';
1361 if (q[1] >= '0' && q[1] <= '7') {
1362 c = (c * 8) + *++q - '0';
1363 if (q[1] >= '0' && q[1] <= '7')
1364 c = (c * 8) + *++q - '0';
1365 }
1366 *r = c;
1367 }
1368 break;
1369
1370 default:
1371 *r = *q;
1372 break;
1373 } else
1374 *r = *q;
1375 }
1376 *r = '\0';
1377 obj_string_patch(f, sym->secidx, sym->value, str);
1378 } else if (*q >= '0' && *q <= '9') {
1379 do
1380 *loc++ = strtoul(q, &q, 0);
1381 while (*q++ == ',');
1382 } else {
1383 char *contents = f->sections[sym->secidx]->contents;
1384 char *loc = contents + sym->value;
1385 char *r; /* To search for commas */
1386
1387 /* Break the string with comas */
1388 while ((r = strchr(q, ',')) != (char *) NULL) {
1389 *r++ = '\0';
1390 obj_string_patch(f, sym->secidx, loc - contents, q);
1391 loc += sizeof(char *);
1392 q = r;
1393 }
1394
1395 /* last part */
1396 obj_string_patch(f, sym->secidx, loc - contents, q);
1397 }
1398
1399 argc--, argv++;
1400 }
1401
1402 return 1;
1403}
1404
1405#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1406static int old_is_module_checksummed(struct obj_file *f)
1407{
1408 return obj_find_symbol(f, "Using_Versions") != NULL;
1409}
1410/* Get the module's kernel version in the canonical integer form. */
1411
1412static int
1413old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1414{
1415 struct obj_symbol *sym;
1416 char *p, *q;
1417 int a, b, c;
1418
1419 sym = obj_find_symbol(f, "kernel_version");
1420 if (sym == NULL)
1421 return -1;
1422
1423 p = f->sections[sym->secidx]->contents + sym->value;
1424 strncpy(str, p, STRVERSIONLEN);
1425
1426 a = strtoul(p, &p, 10);
1427 if (*p != '.')
1428 return -1;
1429 b = strtoul(p + 1, &p, 10);
1430 if (*p != '.')
1431 return -1;
1432 c = strtoul(p + 1, &q, 10);
1433 if (p + 1 == q)
1434 return -1;
1435
1436 return a << 16 | b << 8 | c;
1437}
1438
1439#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1440
1441#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
1442
1443/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1444
Eric Andersen8c185f92000-09-22 00:38:07 +00001445static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001446{
1447 struct old_kernel_sym *ks, *k;
1448 struct new_module_symbol *s;
1449 struct external_module *mod;
1450 int nks, nms, nmod, i;
1451
1452 nks = get_kernel_syms(NULL);
1453 if (nks < 0) {
Eric Andersen8a24a672000-06-22 18:19:31 +00001454 errorMsg("get_kernel_syms: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001455 return 0;
1456 }
1457
1458 ks = k = xmalloc(nks * sizeof(*ks));
1459
1460 if (get_kernel_syms(ks) != nks) {
1461 perror("inconsistency with get_kernel_syms -- is someone else "
1462 "playing with modules?");
1463 free(ks);
1464 return 0;
1465 }
1466
1467 /* Collect the module information. */
1468
1469 mod = NULL;
1470 nmod = -1;
1471
1472 while (k->name[0] == '#' && k->name[1]) {
1473 struct old_kernel_sym *k2;
1474 struct new_module_symbol *s;
1475
1476 /* Find out how many symbols this module has. */
1477 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1478 continue;
1479 nms = k2 - k - 1;
1480
1481 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1482 mod[nmod].name = k->name + 1;
1483 mod[nmod].addr = k->value;
1484 mod[nmod].used = 0;
1485 mod[nmod].nsyms = nms;
1486 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1487
1488 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1489 s->name = (unsigned long) k->name;
1490 s->value = k->value;
1491 }
1492
1493 k = k2;
1494 }
1495
1496 ext_modules = mod;
1497 n_ext_modules = nmod + 1;
1498
1499 /* Now collect the symbols for the kernel proper. */
1500
1501 if (k->name[0] == '#')
1502 ++k;
1503
1504 nksyms = nms = nks - (k - ks);
1505 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1506
1507 for (i = 0; i < nms; ++i, ++s, ++k) {
1508 s->name = (unsigned long) k->name;
1509 s->value = k->value;
1510 }
1511
1512 return 1;
1513}
1514
1515/* Return the kernel symbol checksum version, or zero if not used. */
1516
1517static int old_is_kernel_checksummed(void)
1518{
1519 /* Using_Versions is the first symbol. */
1520 if (nksyms > 0
1521 && strcmp((char *) ksyms[0].name,
1522 "Using_Versions") == 0) return ksyms[0].value;
1523 else
1524 return 0;
1525}
1526
1527
1528static int old_create_mod_use_count(struct obj_file *f)
1529{
1530 struct obj_section *sec;
1531
1532 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1533 sizeof(long));
1534
1535 obj_add_symbol(f, "mod_use_count_", -1,
1536 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1537 sizeof(long));
1538
1539 return 1;
1540}
1541
1542static int
1543old_init_module(const char *m_name, struct obj_file *f,
1544 unsigned long m_size)
1545{
1546 char *image;
1547 struct old_mod_routines routines;
1548 struct old_symbol_table *symtab;
1549 int ret;
1550
1551 /* Create the symbol table */
1552 {
1553 int nsyms = 0, strsize = 0, total;
1554
1555 /* Size things first... */
1556 if (flag_export) {
1557 int i;
1558 for (i = 0; i < HASH_BUCKETS; ++i) {
1559 struct obj_symbol *sym;
1560 for (sym = f->symtab[i]; sym; sym = sym->next)
1561 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1562 && sym->secidx <= SHN_HIRESERVE)
1563 {
1564 sym->ksymidx = nsyms++;
1565 strsize += strlen(sym->name) + 1;
1566 }
1567 }
1568 }
1569
1570 total = (sizeof(struct old_symbol_table)
1571 + nsyms * sizeof(struct old_module_symbol)
1572 + n_ext_modules_used * sizeof(struct old_module_ref)
1573 + strsize);
1574 symtab = xmalloc(total);
1575 symtab->size = total;
1576 symtab->n_symbols = nsyms;
1577 symtab->n_refs = n_ext_modules_used;
1578
1579 if (flag_export && nsyms) {
1580 struct old_module_symbol *ksym;
1581 char *str;
1582 int i;
1583
1584 ksym = symtab->symbol;
1585 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1586 + n_ext_modules_used * sizeof(struct old_module_ref));
1587
1588 for (i = 0; i < HASH_BUCKETS; ++i) {
1589 struct obj_symbol *sym;
1590 for (sym = f->symtab[i]; sym; sym = sym->next)
1591 if (sym->ksymidx >= 0) {
1592 ksym->addr = obj_symbol_final_value(f, sym);
1593 ksym->name =
1594 (unsigned long) str - (unsigned long) symtab;
1595
1596 str = stpcpy(str, sym->name) + 1;
1597 ksym++;
1598 }
1599 }
1600 }
1601
1602 if (n_ext_modules_used) {
1603 struct old_module_ref *ref;
1604 int i;
1605
1606 ref = (struct old_module_ref *)
1607 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1608
1609 for (i = 0; i < n_ext_modules; ++i)
1610 if (ext_modules[i].used)
1611 ref++->module = ext_modules[i].addr;
1612 }
1613 }
1614
1615 /* Fill in routines. */
1616
1617 routines.init =
1618 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1619 routines.cleanup =
1620 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1621
1622 /* Whew! All of the initialization is complete. Collect the final
1623 module image and give it to the kernel. */
1624
1625 image = xmalloc(m_size);
1626 obj_create_image(f, image);
1627
1628 /* image holds the complete relocated module, accounting correctly for
1629 mod_use_count. However the old module kernel support assume that
1630 it is receiving something which does not contain mod_use_count. */
1631 ret = old_sys_init_module(m_name, image + sizeof(long),
1632 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1633 : 0), &routines, symtab);
1634 if (ret)
Eric Andersen8a24a672000-06-22 18:19:31 +00001635 errorMsg("init_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001636
1637 free(image);
1638 free(symtab);
1639
1640 return ret == 0;
1641}
1642
1643#else
1644
1645#define old_create_mod_use_count(x) TRUE
1646#define old_init_module(x, y, z) TRUE
1647
1648#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
1649
1650
1651
1652/*======================================================================*/
1653/* Functions relating to module loading after 2.1.18. */
1654
1655static int
1656new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1657{
1658 while (argc > 0) {
1659 char *p, *q, *key;
1660 struct obj_symbol *sym;
1661 char *contents, *loc;
1662 int min, max, n;
1663
1664 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001665 if ((q = strchr(p, '=')) == NULL) {
1666 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001667 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001668 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001669
1670 key = alloca(q - p + 6);
1671 memcpy(key, "parm_", 5);
1672 memcpy(key + 5, p, q - p);
1673 key[q - p + 5] = 0;
1674
1675 p = get_modinfo_value(f, key);
1676 key += 5;
1677 if (p == NULL) {
Matt Kraaid537a952000-07-14 01:51:25 +00001678 errorMsg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001679 return 0;
1680 }
1681
1682 sym = obj_find_symbol(f, key);
1683
1684 /* Also check that the parameter was not resolved from the kernel. */
1685 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001686 errorMsg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001687 return 0;
1688 }
1689
1690 if (isdigit(*p)) {
1691 min = strtoul(p, &p, 10);
1692 if (*p == '-')
1693 max = strtoul(p + 1, &p, 10);
1694 else
1695 max = min;
1696 } else
1697 min = max = 1;
1698
1699 contents = f->sections[sym->secidx]->contents;
1700 loc = contents + sym->value;
1701 n = (*++q != '\0');
1702
1703 while (1) {
1704 if ((*p == 's') || (*p == 'c')) {
1705 char *str;
1706
1707 /* Do C quoting if we begin with a ", else slurp the lot. */
1708 if (*q == '"') {
1709 char *r;
1710
1711 str = alloca(strlen(q));
1712 for (r = str, q++; *q != '"'; ++q, ++r) {
1713 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001714 errorMsg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001715 key);
1716 return 0;
1717 } else if (*q == '\\')
1718 switch (*++q) {
1719 case 'a':
1720 *r = '\a';
1721 break;
1722 case 'b':
1723 *r = '\b';
1724 break;
1725 case 'e':
1726 *r = '\033';
1727 break;
1728 case 'f':
1729 *r = '\f';
1730 break;
1731 case 'n':
1732 *r = '\n';
1733 break;
1734 case 'r':
1735 *r = '\r';
1736 break;
1737 case 't':
1738 *r = '\t';
1739 break;
1740
1741 case '0':
1742 case '1':
1743 case '2':
1744 case '3':
1745 case '4':
1746 case '5':
1747 case '6':
1748 case '7':
1749 {
1750 int c = *q - '0';
1751 if (q[1] >= '0' && q[1] <= '7') {
1752 c = (c * 8) + *++q - '0';
1753 if (q[1] >= '0' && q[1] <= '7')
1754 c = (c * 8) + *++q - '0';
1755 }
1756 *r = c;
1757 }
1758 break;
1759
1760 default:
1761 *r = *q;
1762 break;
1763 } else
1764 *r = *q;
1765 }
1766 *r = '\0';
1767 ++q;
1768 } else {
1769 char *r;
1770
1771 /* In this case, the string is not quoted. We will break
1772 it using the coma (like for ints). If the user wants to
1773 include comas in a string, he just has to quote it */
1774
1775 /* Search the next coma */
1776 r = strchr(q, ',');
1777
1778 /* Found ? */
1779 if (r != (char *) NULL) {
1780 /* Recopy the current field */
1781 str = alloca(r - q + 1);
1782 memcpy(str, q, r - q);
1783
1784 /* I don't know if it is usefull, as the previous case
1785 doesn't null terminate the string ??? */
1786 str[r - q] = '\0';
1787
1788 /* Keep next fields */
1789 q = r;
1790 } else {
1791 /* last string */
1792 str = q;
1793 q = "";
1794 }
1795 }
1796
1797 if (*p == 's') {
1798 /* Normal string */
1799 obj_string_patch(f, sym->secidx, loc - contents, str);
1800 loc += tgt_sizeof_char_p;
1801 } else {
1802 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001803 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001804
1805 /* Get the size of each member */
1806 /* Probably we should do that outside the loop ? */
1807 if (!isdigit(*(p + 1))) {
Matt Kraaid537a952000-07-14 01:51:25 +00001808 errorMsg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001809 " the maximum size\n", key);
1810 return 0;
1811 }
1812 charssize = strtoul(p + 1, (char **) NULL, 10);
1813
1814 /* Check length */
1815 if (strlen(str) >= charssize) {
Matt Kraaid537a952000-07-14 01:51:25 +00001816 errorMsg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001817 charssize - 1);
1818 return 0;
1819 }
1820
1821 /* Copy to location */
1822 strcpy((char *) loc, str);
1823 loc += charssize;
1824 }
1825 } else {
1826 long v = strtoul(q, &q, 0);
1827 switch (*p) {
1828 case 'b':
1829 *loc++ = v;
1830 break;
1831 case 'h':
1832 *(short *) loc = v;
1833 loc += tgt_sizeof_short;
1834 break;
1835 case 'i':
1836 *(int *) loc = v;
1837 loc += tgt_sizeof_int;
1838 break;
1839 case 'l':
1840 *(long *) loc = v;
1841 loc += tgt_sizeof_long;
1842 break;
1843
1844 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001845 errorMsg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001846 return 0;
1847 }
1848 }
1849
1850 retry_end_of_value:
1851 switch (*q) {
1852 case '\0':
1853 goto end_of_arg;
1854
1855 case ' ':
1856 case '\t':
1857 case '\n':
1858 case '\r':
1859 ++q;
1860 goto retry_end_of_value;
1861
1862 case ',':
1863 if (++n > max) {
Matt Kraaid537a952000-07-14 01:51:25 +00001864 errorMsg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001865 return 0;
1866 }
1867 ++q;
1868 break;
1869
1870 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001871 errorMsg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001872 return 0;
1873 }
1874 }
1875
1876 end_of_arg:
1877 if (n < min) {
Matt Kraaid537a952000-07-14 01:51:25 +00001878 errorMsg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001879 return 0;
1880 }
1881
1882 argc--, argv++;
1883 }
1884
1885 return 1;
1886}
1887
1888#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1889static int new_is_module_checksummed(struct obj_file *f)
1890{
1891 const char *p = get_modinfo_value(f, "using_checksums");
1892 if (p)
1893 return atoi(p);
1894 else
1895 return 0;
1896}
1897
1898/* Get the module's kernel version in the canonical integer form. */
1899
1900static int
1901new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1902{
1903 char *p, *q;
1904 int a, b, c;
1905
1906 p = get_modinfo_value(f, "kernel_version");
1907 if (p == NULL)
1908 return -1;
1909 strncpy(str, p, STRVERSIONLEN);
1910
1911 a = strtoul(p, &p, 10);
1912 if (*p != '.')
1913 return -1;
1914 b = strtoul(p + 1, &p, 10);
1915 if (*p != '.')
1916 return -1;
1917 c = strtoul(p + 1, &q, 10);
1918 if (p + 1 == q)
1919 return -1;
1920
1921 return a << 16 | b << 8 | c;
1922}
1923
1924#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1925
1926
1927#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
1928
1929/* Fetch the loaded modules, and all currently exported symbols. */
1930
1931static int new_get_kernel_symbols(void)
1932{
1933 char *module_names, *mn;
1934 struct external_module *modules, *m;
1935 struct new_module_symbol *syms, *s;
1936 size_t ret, bufsize, nmod, nsyms, i, j;
1937
1938 /* Collect the loaded modules. */
1939
1940 module_names = xmalloc(bufsize = 256);
1941 retry_modules_load:
1942 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
1943 if (errno == ENOSPC) {
1944 module_names = xrealloc(module_names, bufsize = ret);
1945 goto retry_modules_load;
1946 }
Eric Andersen8a24a672000-06-22 18:19:31 +00001947 errorMsg("QM_MODULES: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001948 return 0;
1949 }
1950
1951 n_ext_modules = nmod = ret;
1952 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
1953 memset(modules, 0, nmod * sizeof(*modules));
1954
1955 /* Collect the modules' symbols. */
1956
1957 for (i = 0, mn = module_names, m = modules;
1958 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
1959 struct new_module_info info;
1960
1961 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
1962 if (errno == ENOENT) {
1963 /* The module was removed out from underneath us. */
1964 continue;
1965 }
Eric Andersen8a24a672000-06-22 18:19:31 +00001966 errorMsg("query_module: QM_INFO: %s: %s", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001967 return 0;
1968 }
1969
1970 syms = xmalloc(bufsize = 1024);
1971 retry_mod_sym_load:
1972 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
1973 switch (errno) {
1974 case ENOSPC:
1975 syms = xrealloc(syms, bufsize = ret);
1976 goto retry_mod_sym_load;
1977 case ENOENT:
1978 /* The module was removed out from underneath us. */
1979 continue;
1980 default:
Eric Andersen8a24a672000-06-22 18:19:31 +00001981 errorMsg("query_module: QM_SYMBOLS: %s: %s", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001982 return 0;
1983 }
1984 }
1985 nsyms = ret;
1986
1987 m->name = mn;
1988 m->addr = info.addr;
1989 m->nsyms = nsyms;
1990 m->syms = syms;
1991
1992 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1993 s->name += (unsigned long) syms;
1994 }
1995 }
1996
1997 /* Collect the kernel's symbols. */
1998
1999 syms = xmalloc(bufsize = 16 * 1024);
2000 retry_kern_sym_load:
2001 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2002 if (errno == ENOSPC) {
2003 syms = xrealloc(syms, bufsize = ret);
2004 goto retry_kern_sym_load;
2005 }
Eric Andersen8a24a672000-06-22 18:19:31 +00002006 errorMsg("kernel: QM_SYMBOLS: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002007 return 0;
2008 }
2009 nksyms = nsyms = ret;
2010 ksyms = syms;
2011
2012 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2013 s->name += (unsigned long) syms;
2014 }
2015 return 1;
2016}
2017
2018
2019/* Return the kernel symbol checksum version, or zero if not used. */
2020
2021static int new_is_kernel_checksummed(void)
2022{
2023 struct new_module_symbol *s;
2024 size_t i;
2025
2026 /* Using_Versions is not the first symbol, but it should be in there. */
2027
2028 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2029 if (strcmp((char *) s->name, "Using_Versions") == 0)
2030 return s->value;
2031
2032 return 0;
2033}
2034
2035
2036static int new_create_this_module(struct obj_file *f, const char *m_name)
2037{
2038 struct obj_section *sec;
2039
2040 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2041 sizeof(struct new_module));
2042 memset(sec->contents, 0, sizeof(struct new_module));
2043
2044 obj_add_symbol(f, "__this_module", -1,
2045 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2046 sizeof(struct new_module));
2047
2048 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2049 m_name);
2050
2051 return 1;
2052}
2053
2054
2055static int new_create_module_ksymtab(struct obj_file *f)
2056{
2057 struct obj_section *sec;
2058 int i;
2059
2060 /* We must always add the module references. */
2061
2062 if (n_ext_modules_used) {
2063 struct new_module_ref *dep;
2064 struct obj_symbol *tm;
2065
2066 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2067 (sizeof(struct new_module_ref)
2068 * n_ext_modules_used));
2069 if (!sec)
2070 return 0;
2071
2072 tm = obj_find_symbol(f, "__this_module");
2073 dep = (struct new_module_ref *) sec->contents;
2074 for (i = 0; i < n_ext_modules; ++i)
2075 if (ext_modules[i].used) {
2076 dep->dep = ext_modules[i].addr;
2077 obj_symbol_patch(f, sec->idx,
2078 (char *) &dep->ref - sec->contents, tm);
2079 dep->next_ref = 0;
2080 ++dep;
2081 }
2082 }
2083
2084 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2085 size_t nsyms;
2086 int *loaded;
2087
2088 sec =
2089 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2090 0);
2091
2092 /* We don't want to export symbols residing in sections that
2093 aren't loaded. There are a number of these created so that
2094 we make sure certain module options don't appear twice. */
2095
2096 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2097 while (--i >= 0)
2098 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2099
2100 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2101 struct obj_symbol *sym;
2102 for (sym = f->symtab[i]; sym; sym = sym->next)
2103 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2104 && sym->secidx <= SHN_HIRESERVE
2105 && (sym->secidx >= SHN_LORESERVE
2106 || loaded[sym->secidx])) {
2107 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2108
2109 obj_symbol_patch(f, sec->idx, ofs, sym);
2110 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2111 sym->name);
2112
2113 nsyms++;
2114 }
2115 }
2116
2117 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2118 }
2119
2120 return 1;
2121}
2122
2123
2124static int
2125new_init_module(const char *m_name, struct obj_file *f,
2126 unsigned long m_size)
2127{
2128 struct new_module *module;
2129 struct obj_section *sec;
2130 void *image;
2131 int ret;
2132 tgt_long m_addr;
2133
2134 sec = obj_find_section(f, ".this");
2135 module = (struct new_module *) sec->contents;
2136 m_addr = sec->header.sh_addr;
2137
2138 module->size_of_struct = sizeof(*module);
2139 module->size = m_size;
2140 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2141
2142 sec = obj_find_section(f, "__ksymtab");
2143 if (sec && sec->header.sh_size) {
2144 module->syms = sec->header.sh_addr;
2145 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2146 }
2147
2148 if (n_ext_modules_used) {
2149 sec = obj_find_section(f, ".kmodtab");
2150 module->deps = sec->header.sh_addr;
2151 module->ndeps = n_ext_modules_used;
2152 }
2153
2154 module->init =
2155 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2156 module->cleanup =
2157 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2158
2159 sec = obj_find_section(f, "__ex_table");
2160 if (sec) {
2161 module->ex_table_start = sec->header.sh_addr;
2162 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2163 }
2164
2165 sec = obj_find_section(f, ".text.init");
2166 if (sec) {
2167 module->runsize = sec->header.sh_addr - m_addr;
2168 }
2169 sec = obj_find_section(f, ".data.init");
2170 if (sec) {
2171 if (!module->runsize ||
2172 module->runsize > sec->header.sh_addr - m_addr)
2173 module->runsize = sec->header.sh_addr - m_addr;
2174 }
2175
2176 if (!arch_init_module(f, module))
2177 return 0;
2178
2179 /* Whew! All of the initialization is complete. Collect the final
2180 module image and give it to the kernel. */
2181
2182 image = xmalloc(m_size);
2183 obj_create_image(f, image);
2184
2185 ret = new_sys_init_module(m_name, (struct new_module *) image);
2186 if (ret)
Eric Andersen8a24a672000-06-22 18:19:31 +00002187 errorMsg("init_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002188
2189 free(image);
2190
2191 return ret == 0;
2192}
2193
2194#else
2195
2196#define new_init_module(x, y, z) TRUE
2197#define new_create_this_module(x, y) 0
2198#define new_create_module_ksymtab(x)
2199
2200#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
2201
2202
2203/*======================================================================*/
2204
2205int
2206obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2207 const char *string)
2208{
2209 struct obj_string_patch *p;
2210 struct obj_section *strsec;
2211 size_t len = strlen(string) + 1;
2212 char *loc;
2213
2214 p = xmalloc(sizeof(*p));
2215 p->next = f->string_patches;
2216 p->reloc_secidx = secidx;
2217 p->reloc_offset = offset;
2218 f->string_patches = p;
2219
2220 strsec = obj_find_section(f, ".kstrtab");
2221 if (strsec == NULL) {
2222 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2223 p->string_offset = 0;
2224 loc = strsec->contents;
2225 } else {
2226 p->string_offset = strsec->header.sh_size;
2227 loc = obj_extend_section(strsec, len);
2228 }
2229 memcpy(loc, string, len);
2230
2231 return 1;
2232}
2233
2234int
2235obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2236 struct obj_symbol *sym)
2237{
2238 struct obj_symbol_patch *p;
2239
2240 p = xmalloc(sizeof(*p));
2241 p->next = f->symbol_patches;
2242 p->reloc_secidx = secidx;
2243 p->reloc_offset = offset;
2244 p->sym = sym;
2245 f->symbol_patches = p;
2246
2247 return 1;
2248}
2249
2250int obj_check_undefineds(struct obj_file *f)
2251{
2252 unsigned long i;
2253 int ret = 1;
2254
2255 for (i = 0; i < HASH_BUCKETS; ++i) {
2256 struct obj_symbol *sym;
2257 for (sym = f->symtab[i]; sym; sym = sym->next)
2258 if (sym->secidx == SHN_UNDEF) {
2259 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2260 sym->secidx = SHN_ABS;
2261 sym->value = 0;
2262 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002263 errorMsg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002264 ret = 0;
2265 }
2266 }
2267 }
2268
2269 return ret;
2270}
2271
2272void obj_allocate_commons(struct obj_file *f)
2273{
2274 struct common_entry {
2275 struct common_entry *next;
2276 struct obj_symbol *sym;
2277 } *common_head = NULL;
2278
2279 unsigned long i;
2280
2281 for (i = 0; i < HASH_BUCKETS; ++i) {
2282 struct obj_symbol *sym;
2283 for (sym = f->symtab[i]; sym; sym = sym->next)
2284 if (sym->secidx == SHN_COMMON) {
2285 /* Collect all COMMON symbols and sort them by size so as to
2286 minimize space wasted by alignment requirements. */
2287 {
2288 struct common_entry **p, *n;
2289 for (p = &common_head; *p; p = &(*p)->next)
2290 if (sym->size <= (*p)->sym->size)
2291 break;
2292
2293 n = alloca(sizeof(*n));
2294 n->next = *p;
2295 n->sym = sym;
2296 *p = n;
2297 }
2298 }
2299 }
2300
2301 for (i = 1; i < f->local_symtab_size; ++i) {
2302 struct obj_symbol *sym = f->local_symtab[i];
2303 if (sym && sym->secidx == SHN_COMMON) {
2304 struct common_entry **p, *n;
2305 for (p = &common_head; *p; p = &(*p)->next)
2306 if (sym == (*p)->sym)
2307 break;
2308 else if (sym->size < (*p)->sym->size) {
2309 n = alloca(sizeof(*n));
2310 n->next = *p;
2311 n->sym = sym;
2312 *p = n;
2313 break;
2314 }
2315 }
2316 }
2317
2318 if (common_head) {
2319 /* Find the bss section. */
2320 for (i = 0; i < f->header.e_shnum; ++i)
2321 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2322 break;
2323
2324 /* If for some reason there hadn't been one, create one. */
2325 if (i == f->header.e_shnum) {
2326 struct obj_section *sec;
2327
2328 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2329 f->sections[i] = sec = arch_new_section();
2330 f->header.e_shnum = i + 1;
2331
2332 memset(sec, 0, sizeof(*sec));
2333 sec->header.sh_type = SHT_PROGBITS;
2334 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2335 sec->name = ".bss";
2336 sec->idx = i;
2337 }
2338
2339 /* Allocate the COMMONS. */
2340 {
2341 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2342 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2343 struct common_entry *c;
2344
2345 for (c = common_head; c; c = c->next) {
2346 ElfW(Addr) align = c->sym->value;
2347
2348 if (align > max_align)
2349 max_align = align;
2350 if (bss_size & (align - 1))
2351 bss_size = (bss_size | (align - 1)) + 1;
2352
2353 c->sym->secidx = i;
2354 c->sym->value = bss_size;
2355
2356 bss_size += c->sym->size;
2357 }
2358
2359 f->sections[i]->header.sh_size = bss_size;
2360 f->sections[i]->header.sh_addralign = max_align;
2361 }
2362 }
2363
2364 /* For the sake of patch relocation and parameter initialization,
2365 allocate zeroed data for NOBITS sections now. Note that after
2366 this we cannot assume NOBITS are really empty. */
2367 for (i = 0; i < f->header.e_shnum; ++i) {
2368 struct obj_section *s = f->sections[i];
2369 if (s->header.sh_type == SHT_NOBITS) {
2370 s->contents = memset(xmalloc(s->header.sh_size),
2371 0, s->header.sh_size);
2372 s->header.sh_type = SHT_PROGBITS;
2373 }
2374 }
2375}
2376
2377unsigned long obj_load_size(struct obj_file *f)
2378{
2379 unsigned long dot = 0;
2380 struct obj_section *sec;
2381
2382 /* Finalize the positions of the sections relative to one another. */
2383
2384 for (sec = f->load_order; sec; sec = sec->load_next) {
2385 ElfW(Addr) align;
2386
2387 align = sec->header.sh_addralign;
2388 if (align && (dot & (align - 1)))
2389 dot = (dot | (align - 1)) + 1;
2390
2391 sec->header.sh_addr = dot;
2392 dot += sec->header.sh_size;
2393 }
2394
2395 return dot;
2396}
2397
2398int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2399{
2400 int i, n = f->header.e_shnum;
2401 int ret = 1;
2402
2403 /* Finalize the addresses of the sections. */
2404
2405 f->baseaddr = base;
2406 for (i = 0; i < n; ++i)
2407 f->sections[i]->header.sh_addr += base;
2408
2409 /* And iterate over all of the relocations. */
2410
2411 for (i = 0; i < n; ++i) {
2412 struct obj_section *relsec, *symsec, *targsec, *strsec;
2413 ElfW(RelM) * rel, *relend;
2414 ElfW(Sym) * symtab;
2415 const char *strtab;
2416
2417 relsec = f->sections[i];
2418 if (relsec->header.sh_type != SHT_RELM)
2419 continue;
2420
2421 symsec = f->sections[relsec->header.sh_link];
2422 targsec = f->sections[relsec->header.sh_info];
2423 strsec = f->sections[symsec->header.sh_link];
2424
2425 rel = (ElfW(RelM) *) relsec->contents;
2426 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2427 symtab = (ElfW(Sym) *) symsec->contents;
2428 strtab = (const char *) strsec->contents;
2429
2430 for (; rel < relend; ++rel) {
2431 ElfW(Addr) value = 0;
2432 struct obj_symbol *intsym = NULL;
2433 unsigned long symndx;
2434 ElfW(Sym) * extsym = 0;
2435 const char *errmsg;
2436
2437 /* Attempt to find a value to use for this relocation. */
2438
2439 symndx = ELFW(R_SYM) (rel->r_info);
2440 if (symndx) {
2441 /* Note we've already checked for undefined symbols. */
2442
2443 extsym = &symtab[symndx];
2444 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2445 /* Local symbols we look up in the local table to be sure
2446 we get the one that is really intended. */
2447 intsym = f->local_symtab[symndx];
2448 } else {
2449 /* Others we look up in the hash table. */
2450 const char *name;
2451 if (extsym->st_name)
2452 name = strtab + extsym->st_name;
2453 else
2454 name = f->sections[extsym->st_shndx]->name;
2455 intsym = obj_find_symbol(f, name);
2456 }
2457
2458 value = obj_symbol_final_value(f, intsym);
2459 intsym->referenced = 1;
2460 }
2461#if SHT_RELM == SHT_RELA
2462#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2463 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2464 if (!extsym || !extsym->st_name ||
2465 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2466#endif
2467 value += rel->r_addend;
2468#endif
2469
2470 /* Do it! */
2471 switch (arch_apply_relocation
2472 (f, targsec, symsec, intsym, rel, value)) {
2473 case obj_reloc_ok:
2474 break;
2475
2476 case obj_reloc_overflow:
2477 errmsg = "Relocation overflow";
2478 goto bad_reloc;
2479 case obj_reloc_dangerous:
2480 errmsg = "Dangerous relocation";
2481 goto bad_reloc;
2482 case obj_reloc_unhandled:
2483 errmsg = "Unhandled relocation";
2484 bad_reloc:
2485 if (extsym) {
Matt Kraaid537a952000-07-14 01:51:25 +00002486 errorMsg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002487 (long) ELFW(R_TYPE) (rel->r_info),
2488 strtab + extsym->st_name);
2489 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002490 errorMsg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002491 (long) ELFW(R_TYPE) (rel->r_info));
2492 }
2493 ret = 0;
2494 break;
2495 }
2496 }
2497 }
2498
2499 /* Finally, take care of the patches. */
2500
2501 if (f->string_patches) {
2502 struct obj_string_patch *p;
2503 struct obj_section *strsec;
2504 ElfW(Addr) strsec_base;
2505 strsec = obj_find_section(f, ".kstrtab");
2506 strsec_base = strsec->header.sh_addr;
2507
2508 for (p = f->string_patches; p; p = p->next) {
2509 struct obj_section *targsec = f->sections[p->reloc_secidx];
2510 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2511 = strsec_base + p->string_offset;
2512 }
2513 }
2514
2515 if (f->symbol_patches) {
2516 struct obj_symbol_patch *p;
2517
2518 for (p = f->symbol_patches; p; p = p->next) {
2519 struct obj_section *targsec = f->sections[p->reloc_secidx];
2520 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2521 = obj_symbol_final_value(f, p->sym);
2522 }
2523 }
2524
2525 return ret;
2526}
2527
2528int obj_create_image(struct obj_file *f, char *image)
2529{
2530 struct obj_section *sec;
2531 ElfW(Addr) base = f->baseaddr;
2532
2533 for (sec = f->load_order; sec; sec = sec->load_next) {
2534 char *secimg;
2535
2536 if (sec->header.sh_size == 0)
2537 continue;
2538
2539 secimg = image + (sec->header.sh_addr - base);
2540
2541 /* Note that we allocated data for NOBITS sections earlier. */
2542 memcpy(secimg, sec->contents, sec->header.sh_size);
2543 }
2544
2545 return 1;
2546}
2547
2548/*======================================================================*/
2549
2550struct obj_file *obj_load(FILE * fp)
2551{
2552 struct obj_file *f;
2553 ElfW(Shdr) * section_headers;
2554 int shnum, i;
2555 char *shstrtab;
2556
2557 /* Read the file header. */
2558
2559 f = arch_new_file();
2560 memset(f, 0, sizeof(*f));
2561 f->symbol_cmp = strcmp;
2562 f->symbol_hash = obj_elf_hash;
2563 f->load_order_search_start = &f->load_order;
2564
2565 fseek(fp, 0, SEEK_SET);
2566 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002567 errorMsg("error reading ELF header: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002568 return NULL;
2569 }
2570
2571 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2572 || f->header.e_ident[EI_MAG1] != ELFMAG1
2573 || f->header.e_ident[EI_MAG2] != ELFMAG2
2574 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaid537a952000-07-14 01:51:25 +00002575 errorMsg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002576 return NULL;
2577 }
2578 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2579 || f->header.e_ident[EI_DATA] != ELFDATAM
2580 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2581 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaid537a952000-07-14 01:51:25 +00002582 errorMsg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002583 return NULL;
2584 }
2585 if (f->header.e_type != ET_REL) {
Matt Kraaid537a952000-07-14 01:51:25 +00002586 errorMsg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002587 return NULL;
2588 }
2589
2590 /* Read the section headers. */
2591
2592 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002593 errorMsg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002594 (unsigned long) f->header.e_shentsize,
2595 (unsigned long) sizeof(ElfW(Shdr)));
2596 return NULL;
2597 }
2598
2599 shnum = f->header.e_shnum;
2600 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2601 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2602
2603 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2604 fseek(fp, f->header.e_shoff, SEEK_SET);
2605 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002606 errorMsg("error reading ELF section headers: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002607 return NULL;
2608 }
2609
2610 /* Read the section data. */
2611
2612 for (i = 0; i < shnum; ++i) {
2613 struct obj_section *sec;
2614
2615 f->sections[i] = sec = arch_new_section();
2616 memset(sec, 0, sizeof(*sec));
2617
2618 sec->header = section_headers[i];
2619 sec->idx = i;
2620
2621 switch (sec->header.sh_type) {
2622 case SHT_NULL:
2623 case SHT_NOTE:
2624 case SHT_NOBITS:
2625 /* ignore */
2626 break;
2627
2628 case SHT_PROGBITS:
2629 case SHT_SYMTAB:
2630 case SHT_STRTAB:
2631 case SHT_RELM:
2632 if (sec->header.sh_size > 0) {
2633 sec->contents = xmalloc(sec->header.sh_size);
2634 fseek(fp, sec->header.sh_offset, SEEK_SET);
2635 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002636 errorMsg("error reading ELF section data: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002637 return NULL;
2638 }
2639 } else {
2640 sec->contents = NULL;
2641 }
2642 break;
2643
2644#if SHT_RELM == SHT_REL
2645 case SHT_RELA:
Matt Kraaid537a952000-07-14 01:51:25 +00002646 errorMsg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002647 return NULL;
2648#else
2649 case SHT_REL:
Matt Kraaid537a952000-07-14 01:51:25 +00002650 errorMsg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002651 return NULL;
2652#endif
2653
2654 default:
2655 if (sec->header.sh_type >= SHT_LOPROC) {
2656 /* Assume processor specific section types are debug
2657 info and can safely be ignored. If this is ever not
2658 the case (Hello MIPS?), don't put ifdefs here but
2659 create an arch_load_proc_section(). */
2660 break;
2661 }
2662
Matt Kraaid537a952000-07-14 01:51:25 +00002663 errorMsg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002664 (long) sec->header.sh_type);
2665 return NULL;
2666 }
2667 }
2668
2669 /* Do what sort of interpretation as needed by each section. */
2670
2671 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2672
2673 for (i = 0; i < shnum; ++i) {
2674 struct obj_section *sec = f->sections[i];
2675 sec->name = shstrtab + sec->header.sh_name;
2676 }
2677
2678 for (i = 0; i < shnum; ++i) {
2679 struct obj_section *sec = f->sections[i];
2680
2681 if (sec->header.sh_flags & SHF_ALLOC)
2682 obj_insert_section_load_order(f, sec);
2683
2684 switch (sec->header.sh_type) {
2685 case SHT_SYMTAB:
2686 {
2687 unsigned long nsym, j;
2688 char *strtab;
2689 ElfW(Sym) * sym;
2690
2691 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002692 errorMsg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 (unsigned long) sec->header.sh_entsize,
2694 (unsigned long) sizeof(ElfW(Sym)));
2695 return NULL;
2696 }
2697
2698 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2699 strtab = f->sections[sec->header.sh_link]->contents;
2700 sym = (ElfW(Sym) *) sec->contents;
2701
2702 /* Allocate space for a table of local symbols. */
2703 j = f->local_symtab_size = sec->header.sh_info;
2704 f->local_symtab = xmalloc(j *=
2705 sizeof(struct obj_symbol *));
2706 memset(f->local_symtab, 0, j);
2707
2708 /* Insert all symbols into the hash table. */
2709 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2710 const char *name;
2711 if (sym->st_name)
2712 name = strtab + sym->st_name;
2713 else
2714 name = f->sections[sym->st_shndx]->name;
2715
2716 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2717 sym->st_value, sym->st_size);
2718 }
2719 }
2720 break;
2721
2722 case SHT_RELM:
2723 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002724 errorMsg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002725 (unsigned long) sec->header.sh_entsize,
2726 (unsigned long) sizeof(ElfW(RelM)));
2727 return NULL;
2728 }
2729 break;
2730 }
2731 }
2732
2733 return f;
2734}
2735
2736static void hide_special_symbols(struct obj_file *f)
2737{
2738 static const char *const specials[] = {
2739 "cleanup_module",
2740 "init_module",
2741 "kernel_version",
2742 NULL
2743 };
2744
2745 struct obj_symbol *sym;
2746 const char *const *p;
2747
2748 for (p = specials; *p; ++p)
2749 if ((sym = obj_find_symbol(f, *p)) != NULL)
2750 sym->info =
2751 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2752}
2753
2754
2755
2756extern int insmod_main( int argc, char **argv)
2757{
2758 int k_crcs;
2759 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002760 int len;
2761 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002762 unsigned long m_size;
2763 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002764 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002765 struct obj_file *f;
2766 char m_name[BUFSIZ + 1] = "\0";
2767 int exit_status = FALSE;
2768 int m_has_modinfo;
2769#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2770 int k_version;
2771 char k_strversion[STRVERSIONLEN];
2772 char m_strversion[STRVERSIONLEN];
2773 int m_version;
2774 int m_crcs;
2775#endif
2776
Erik Andersen02104321999-12-17 18:57:34 +00002777
Erik Andersene49d5ec2000-02-08 19:58:47 +00002778 if (argc <= 1) {
Erik Andersen02104321999-12-17 18:57:34 +00002779 usage(insmod_usage);
Erik Andersen02104321999-12-17 18:57:34 +00002780 }
Erik Andersen02104321999-12-17 18:57:34 +00002781
Erik Andersene49d5ec2000-02-08 19:58:47 +00002782 /* Parse any options */
2783 while (--argc > 0 && **(++argv) == '-') {
2784 while (*(++(*argv))) {
2785 switch (**argv) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002786 case 'f': /* force loading */
2787 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002788 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002789 case 'k': /* module loaded by kerneld, auto-cleanable */
2790 flag_autoclean = 1;
2791 break;
2792 case 'v': /* verbose output */
2793 flag_verbose = 1;
2794 break;
2795 case 'x': /* do not export externs */
2796 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002797 break;
2798 default:
2799 usage(insmod_usage);
2800 }
2801 }
Erik Andersend387d011999-12-21 02:55:11 +00002802 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002803
Eric Andersen9f16d612000-06-12 23:11:16 +00002804 if (argc <= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002805 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002806 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002807 /* Grab the module name */
Eric Andersen9f16d612000-06-12 23:11:16 +00002808 if ((tmp = strrchr(*argv, '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002809 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002810 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002811 tmp = *argv;
Eric Andersen9f16d612000-06-12 23:11:16 +00002812 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002813 len = strlen(tmp);
2814
2815 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2816 len -= 2;
2817 memcpy(m_name, tmp, len);
2818 strcpy(m_fullName, m_name);
2819 strcat(m_fullName, ".o");
2820
2821 /* Get a filedesc for the module */
2822 if ((fp = fopen(*argv, "r")) == NULL) {
2823 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
2824 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002825 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002826 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002827 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002828 || ((fp = fopen(m_filename, "r")) == NULL))
2829 {
Eric Andersen8a24a672000-06-22 18:19:31 +00002830 errorMsg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002831 exit(FALSE);
2832 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002833 } else
2834 fatalError("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002835 } else
2836 memcpy(m_filename, *argv, strlen(*argv));
Erik Andersend387d011999-12-21 02:55:11 +00002837
2838
Erik Andersene49d5ec2000-02-08 19:58:47 +00002839 if ((f = obj_load(fp)) == NULL) {
2840 perror("Could not load the module\n");
2841 exit(FALSE);
Erik Andersend387d011999-12-21 02:55:11 +00002842 }
Erik Andersend387d011999-12-21 02:55:11 +00002843
Eric Andersen9f16d612000-06-12 23:11:16 +00002844 if (get_modinfo_value(f, "kernel_version") == NULL)
2845 m_has_modinfo = 0;
2846 else
2847 m_has_modinfo = 1;
2848
2849#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2850 /* Version correspondence? */
2851
2852 k_version = get_kernel_version(k_strversion);
2853 if (m_has_modinfo) {
2854 m_version = new_get_module_version(f, m_strversion);
2855 } else {
2856 m_version = old_get_module_version(f, m_strversion);
2857 if (m_version == -1) {
Matt Kraaid537a952000-07-14 01:51:25 +00002858 errorMsg("couldn't find the kernel version the module was "
2859 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002860 goto out;
2861 }
2862 }
2863
2864 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2865 if (flag_force_load) {
Matt Kraaid537a952000-07-14 01:51:25 +00002866 errorMsg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002867 "\t%s was compiled for kernel version %s\n"
2868 "\twhile this kernel is version %s\n",
2869 m_filename, m_strversion, k_strversion);
2870 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002871 errorMsg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002872 "\t%s was compiled for kernel version %s\n"
2873 "\twhile this kernel is version %s.\n",
2874 m_filename, m_strversion, k_strversion);
2875 goto out;
2876 }
2877 }
2878 k_crcs = 0;
2879#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2880
2881 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2882
2883 if (k_new_syscalls) {
2884#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
2885 if (!new_get_kernel_symbols())
2886 goto out;
2887 k_crcs = new_is_kernel_checksummed();
2888#else
Matt Kraaid537a952000-07-14 01:51:25 +00002889 errorMsg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002890 goto out;
2891#endif
2892 } else {
2893#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
Eric Andersen8c185f92000-09-22 00:38:07 +00002894 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00002895 goto out;
2896 k_crcs = old_is_kernel_checksummed();
2897#else
Matt Kraaid537a952000-07-14 01:51:25 +00002898 errorMsg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002899 goto out;
2900#endif
2901 }
2902
2903#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2904 if (m_has_modinfo)
2905 m_crcs = new_is_module_checksummed(f);
2906 else
2907 m_crcs = old_is_module_checksummed(f);
2908
2909 if (m_crcs != k_crcs)
2910 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
2911#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2912
Erik Andersene49d5ec2000-02-08 19:58:47 +00002913 /* Let the module know about the kernel symbols. */
2914 add_kernel_symbols(f);
2915
Eric Andersen9f16d612000-06-12 23:11:16 +00002916 /* Allocate common symbols, symbol tables, and string tables. */
2917
2918 if (k_new_syscalls
2919 ? !new_create_this_module(f, m_name)
2920 : !old_create_mod_use_count(f))
2921 {
2922 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002923 }
2924
Eric Andersen9f16d612000-06-12 23:11:16 +00002925 if (!obj_check_undefineds(f)) {
2926 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002927 }
2928 obj_allocate_commons(f);
2929
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 if (optind < argc) {
2931 if (m_has_modinfo
2932 ? !new_process_module_arguments(f, argc - optind, argv + optind)
2933 : !old_process_module_arguments(f, argc - optind, argv + optind))
2934 {
2935 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002936 }
2937 }
2938
Eric Andersen9f16d612000-06-12 23:11:16 +00002939 arch_create_got(f);
2940 hide_special_symbols(f);
2941
2942 if (k_new_syscalls)
2943 new_create_module_ksymtab(f);
2944
Erik Andersene49d5ec2000-02-08 19:58:47 +00002945 /* Find current size of the module */
2946 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00002947
2948
Erik Andersene49d5ec2000-02-08 19:58:47 +00002949 errno = 0;
2950 m_addr = create_module(m_name, m_size);
2951 switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002952 case 0:
2953 break;
2954 case EEXIST:
Matt Kraaid537a952000-07-14 01:51:25 +00002955 errorMsg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002956 goto out;
2957 case ENOMEM:
Matt Kraaid537a952000-07-14 01:51:25 +00002958 errorMsg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002959 m_size);
2960 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00002961 default:
Eric Andersen8a24a672000-06-22 18:19:31 +00002962 errorMsg("create_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002963 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002964 }
Erik Andersend387d011999-12-21 02:55:11 +00002965
Eric Andersen9f16d612000-06-12 23:11:16 +00002966 if (!obj_relocate(f, m_addr)) {
2967 delete_module(m_name);
2968 goto out;
2969 }
Erik Andersend387d011999-12-21 02:55:11 +00002970
Eric Andersen9f16d612000-06-12 23:11:16 +00002971 if (k_new_syscalls
2972 ? !new_init_module(m_name, f, m_size)
2973 : !old_init_module(m_name, f, m_size))
2974 {
2975 delete_module(m_name);
2976 goto out;
2977 }
2978
2979 exit_status = TRUE;
2980
2981out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00002982 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00002983 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00002984}