blob: 4f96c950e1393d80553d4fba6a42d0705ae6e1c0 [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
Eric Andersen3570a342000-09-25 21:45:58 +000039#include "busybox.h"
Erik Andersen02104321999-12-17 18:57:34 +000040#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
Matt Kraai207061a2000-10-23 18:03:46 +000080#ident "$Id: insmod.c,v 1.28 2000/10/23 18:03:46 kraai 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
Matt Kraai207061a2000-10-23 18:03:46 +0000286#ident "$Id: insmod.c,v 1.28 2000/10/23 18:03:46 kraai 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
Pavel Roskin43f3e612000-09-28 20:52:55 +0000326#ifndef EM_486
327#define MATCH_MACHINE(x) (x == EM_386)
328#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000329#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000330#endif
331
Eric Andersen9f16d612000-06-12 23:11:16 +0000332#define SHT_RELM SHT_REL
333#define Elf32_RelM Elf32_Rel
334
Eric Andersenfe4208f2000-09-24 03:44:29 +0000335#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000336
337#ifndef ElfW
338# if ELFCLASSM == ELFCLASS32
339# define ElfW(x) Elf32_ ## x
340# define ELFW(x) ELF32_ ## x
341# else
342# define ElfW(x) Elf64_ ## x
343# define ELFW(x) ELF64_ ## x
344# endif
345#endif
346
347/* For some reason this is missing from libc5. */
348#ifndef ELF32_ST_INFO
349# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
350#endif
351
352#ifndef ELF64_ST_INFO
353# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
354#endif
355
356struct obj_string_patch;
357struct obj_symbol_patch;
358
359struct obj_section
360{
361 ElfW(Shdr) header;
362 const char *name;
363 char *contents;
364 struct obj_section *load_next;
365 int idx;
366};
367
368struct obj_symbol
369{
370 struct obj_symbol *next; /* hash table link */
371 const char *name;
372 unsigned long value;
373 unsigned long size;
374 int secidx; /* the defining section index/module */
375 int info;
376 int ksymidx; /* for export to the kernel symtab */
377 int referenced; /* actually used in the link */
378};
379
380/* Hardcode the hash table size. We shouldn't be needing so many
381 symbols that we begin to degrade performance, and we get a big win
382 by giving the compiler a constant divisor. */
383
384#define HASH_BUCKETS 521
385
386struct obj_file
387{
388 ElfW(Ehdr) header;
389 ElfW(Addr) baseaddr;
390 struct obj_section **sections;
391 struct obj_section *load_order;
392 struct obj_section **load_order_search_start;
393 struct obj_string_patch *string_patches;
394 struct obj_symbol_patch *symbol_patches;
395 int (*symbol_cmp)(const char *, const char *);
396 unsigned long (*symbol_hash)(const char *);
397 unsigned long local_symtab_size;
398 struct obj_symbol **local_symtab;
399 struct obj_symbol *symtab[HASH_BUCKETS];
400};
401
402enum obj_reloc
403{
404 obj_reloc_ok,
405 obj_reloc_overflow,
406 obj_reloc_dangerous,
407 obj_reloc_unhandled
408};
409
410struct obj_string_patch
411{
412 struct obj_string_patch *next;
413 int reloc_secidx;
414 ElfW(Addr) reloc_offset;
415 ElfW(Addr) string_offset;
416};
417
418struct obj_symbol_patch
419{
420 struct obj_symbol_patch *next;
421 int reloc_secidx;
422 ElfW(Addr) reloc_offset;
423 struct obj_symbol *sym;
424};
425
426
427/* Generic object manipulation routines. */
428
429unsigned long obj_elf_hash(const char *);
430
431unsigned long obj_elf_hash_n(const char *, unsigned long len);
432
433struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
434 unsigned long symidx, int info, int secidx,
435 ElfW(Addr) value, unsigned long size);
436
437struct obj_symbol *obj_find_symbol (struct obj_file *f,
438 const char *name);
439
440ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
441 struct obj_symbol *sym);
442
443void obj_set_symbol_compare(struct obj_file *f,
444 int (*cmp)(const char *, const char *),
445 unsigned long (*hash)(const char *));
446
447struct obj_section *obj_find_section (struct obj_file *f,
448 const char *name);
449
450void obj_insert_section_load_order (struct obj_file *f,
451 struct obj_section *sec);
452
453struct obj_section *obj_create_alloced_section (struct obj_file *f,
454 const char *name,
455 unsigned long align,
456 unsigned long size);
457
458struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
459 const char *name,
460 unsigned long align,
461 unsigned long size);
462
463void *obj_extend_section (struct obj_section *sec, unsigned long more);
464
465int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
466 const char *string);
467
468int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
469 struct obj_symbol *sym);
470
471int obj_check_undefineds(struct obj_file *f);
472
473void obj_allocate_commons(struct obj_file *f);
474
475unsigned long obj_load_size (struct obj_file *f);
476
477int obj_relocate (struct obj_file *f, ElfW(Addr) base);
478
479struct obj_file *obj_load(FILE *f);
480
481int obj_create_image (struct obj_file *f, char *image);
482
483/* Architecture specific manipulation routines. */
484
485struct obj_file *arch_new_file (void);
486
487struct obj_section *arch_new_section (void);
488
489struct obj_symbol *arch_new_symbol (void);
490
491enum obj_reloc arch_apply_relocation (struct obj_file *f,
492 struct obj_section *targsec,
493 struct obj_section *symsec,
494 struct obj_symbol *sym,
495 ElfW(RelM) *rel, ElfW(Addr) value);
496
497int arch_create_got (struct obj_file *f);
498
499struct new_module;
500int arch_init_module (struct obj_file *f, struct new_module *);
501
502#endif /* obj.h */
503//----------------------------------------------------------------------------
504//--------end of modutils obj.h
505//----------------------------------------------------------------------------
506
507
508
509
Erik Andersen02104321999-12-17 18:57:34 +0000510
Erik Andersend387d011999-12-21 02:55:11 +0000511#define _PATH_MODULES "/lib/modules"
Eric Andersen9f16d612000-06-12 23:11:16 +0000512#define STRVERSIONLEN 32
Erik Andersend387d011999-12-21 02:55:11 +0000513
Eric Andersen9f16d612000-06-12 23:11:16 +0000514#if !defined(BB_FEATURE_INSMOD_NEW_KERNEL) && !defined(BB_FEATURE_INSMOD_OLD_KERNEL)
515#error "Must have ether BB_FEATURE_INSMOD_NEW_KERNEL or BB_FEATURE_INSMOD_OLD_KERNEL defined"
516#endif
517
518/*======================================================================*/
519
520int flag_force_load = 0;
521int flag_autoclean = 0;
522int flag_verbose = 0;
523int flag_export = 1;
524
525
526/*======================================================================*/
527
Eric Andersenfe4208f2000-09-24 03:44:29 +0000528/* previously, these were named i386_* but since we could be
529 compiling for the sh, I've renamed them to the more general
530 arch_* These structures are the same between the x86 and SH,
531 and we can't support anything else right now anyway. In the
532 future maybe they should be #if defined'd */
533
534struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000535 int offset;
536 unsigned offset_done:1;
537 unsigned reloc_done:1;
538};
539
Eric Andersenfe4208f2000-09-24 03:44:29 +0000540struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000541 struct obj_file root;
542 struct obj_section *got;
543};
544
Eric Andersenfe4208f2000-09-24 03:44:29 +0000545struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000546 struct obj_symbol root;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000547 struct arch_got_entry gotent;
Eric Andersen9f16d612000-06-12 23:11:16 +0000548};
549
550
Eric Andersen9f16d612000-06-12 23:11:16 +0000551struct external_module {
552 const char *name;
553 ElfW(Addr) addr;
554 int used;
555 size_t nsyms;
556 struct new_module_symbol *syms;
557};
558
559struct new_module_symbol *ksyms;
560size_t nksyms;
561
562struct external_module *ext_modules;
563int n_ext_modules;
564int n_ext_modules_used;
565
Erik Andersend387d011999-12-21 02:55:11 +0000566
567
Erik Andersen02104321999-12-17 18:57:34 +0000568/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000569#define __NR_new_sys_init_module __NR_init_module
570_syscall2(int, new_sys_init_module, const char *, name,
571 const struct new_module *, info)
572#define __NR_old_sys_init_module __NR_init_module
573_syscall5(int, old_sys_init_module, const char *, name, char *, code,
574 unsigned, codesize, struct old_mod_routines *, routines,
575 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000576#ifndef BB_RMMOD
577_syscall1(int, delete_module, const char *, name)
578#else
579extern int delete_module(const char *);
580#endif
581
Eric Andersenfe4208f2000-09-24 03:44:29 +0000582/* This is kind of troublesome. See, we don't actually support
583 the m68k or the arm the same way we support i386 and (now)
584 sh. In doing my SH patch, I just assumed that whatever works
585 for i386 also works for m68k and arm since currently insmod.c
586 does nothing special for them. If this isn't true, the below
587 line is rather misleading IMHO, and someone should either
588 change it or add more proper architecture-dependent support
589 for these boys.
590
591 -- Bryan Rittmeyer <bryan@ixiacom.com> */
592
Erik Andersen02104321999-12-17 18:57:34 +0000593#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
594/* Jump through hoops to fixup error return codes */
595#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000596static inline _syscall2(long, _create_module, const char *, name, size_t,
597 size)
Erik Andersen02104321999-12-17 18:57:34 +0000598unsigned long create_module(const char *name, size_t size)
599{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000600 long ret = _create_module(name, size);
601
602 if (ret == -1 && errno > 125) {
603 ret = -errno;
604 errno = 0;
605 }
606 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000607}
608#else
609_syscall2(unsigned long, create_module, const char *, name, size_t, size)
610#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000611static char m_filename[BUFSIZ + 1] = "\0";
612static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000613
Eric Andersen9f16d612000-06-12 23:11:16 +0000614/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000615
Eric Andersen9f16d612000-06-12 23:11:16 +0000616
617static int findNamedModule(const char *fileName, struct stat *statbuf,
618 void *userDate)
619{
620 char *fullName = (char *) userDate;
621
622
623 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000624 return (FALSE);
625 else {
626 char *tmp = strrchr(fileName, '/');
627
628 if (tmp == NULL)
629 tmp = (char *) fileName;
630 else
631 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000632 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000633 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000634 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000635 return (FALSE);
636 }
Erik Andersend387d011999-12-21 02:55:11 +0000637 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000638 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000639}
640
Erik Andersen02104321999-12-17 18:57:34 +0000641
Eric Andersen9f16d612000-06-12 23:11:16 +0000642/*======================================================================*/
643
644struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000645{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000646 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000647 f = xmalloc(sizeof(*f));
648 f->got = NULL;
649 return &f->root;
650}
651
652struct obj_section *arch_new_section(void)
653{
654 return xmalloc(sizeof(struct obj_section));
655}
656
657struct obj_symbol *arch_new_symbol(void)
658{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000659 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000660 sym = xmalloc(sizeof(*sym));
661 memset(&sym->gotent, 0, sizeof(sym->gotent));
662 return &sym->root;
663}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000664
Eric Andersen9f16d612000-06-12 23:11:16 +0000665enum obj_reloc
666arch_apply_relocation(struct obj_file *f,
667 struct obj_section *targsec,
668 struct obj_section *symsec,
669 struct obj_symbol *sym,
Eric Andersenfe4208f2000-09-24 03:44:29 +0000670#if defined(__sh__)
671 Elf32_Rela * rel, Elf32_Addr v)
672#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000673 Elf32_Rel * rel, Elf32_Addr v)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000674#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000675{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000676 struct arch_file *ifile = (struct arch_file *) f;
677 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000678
679 Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset);
680 Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
681 Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
682
683 enum obj_reloc ret = obj_reloc_ok;
684
685 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000686
687/* even though these constants seem to be the same for
688 the i386 and the sh, we "#if define" them for clarity
689 and in case that ever changes */
690#if defined(__sh__)
691 case R_SH_NONE:
692#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000693 case R_386_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000694#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000695 break;
696
Eric Andersenfe4208f2000-09-24 03:44:29 +0000697#if defined(__sh__)
698 case R_SH_DIR32:
699#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000700 case R_386_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000701#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000702 *loc += v;
703 break;
704
Eric Andersenfe4208f2000-09-24 03:44:29 +0000705#if defined(__sh__)
706 case R_SH_REL32:
707#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000708 case R_386_PLT32:
709 case R_386_PC32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000710#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000711 *loc += v - dot;
712 break;
713
Eric Andersenfe4208f2000-09-24 03:44:29 +0000714#if defined(__sh__)
715 case R_SH_PLT32:
716 *loc = v - dot;
717 break;
718#endif
719
720
721#if defined(__sh__)
722 case R_SH_GLOB_DAT:
723 case R_SH_JMP_SLOT:
724 *loc = v;
725 break;
726#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000727 case R_386_GLOB_DAT:
728 case R_386_JMP_SLOT:
729 *loc = v;
730 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000731#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000732
Eric Andersenfe4208f2000-09-24 03:44:29 +0000733#if defined(__sh__)
734 case R_SH_RELATIVE:
735 *loc += f->baseaddr + rel->r_addend;
736 break;
737#else
738 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000739 *loc += f->baseaddr;
740 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000741#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000742
Eric Andersenfe4208f2000-09-24 03:44:29 +0000743#if defined(__sh__)
744 case R_SH_GOTPC:
745 assert(got != 0);
746 *loc += got - dot + rel->r_addend;;
747 break;
748#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000749 case R_386_GOTPC:
750 assert(got != 0);
751 *loc += got - dot;
752 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000753#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000754
Eric Andersenfe4208f2000-09-24 03:44:29 +0000755#if defined(__sh__)
756 case R_SH_GOT32:
757 assert(isym != NULL);
758 if (!isym->gotent.reloc_done) {
759 isym->gotent.reloc_done = 1;
760 *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
761 v;
762 }
763 *loc += isym->gotent.offset + rel->r_addend;
764 break;
765#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000766 case R_386_GOT32:
767 assert(isym != NULL);
768 if (!isym->gotent.reloc_done) {
769 isym->gotent.reloc_done = 1;
770 *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
771 v;
772 }
773 *loc += isym->gotent.offset;
774 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000776
Eric Andersenfe4208f2000-09-24 03:44:29 +0000777#if defined(__sh__)
778 case R_SH_GOTOFF:
779#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000780 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000781#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000782 assert(got != 0);
783 *loc += v - got;
784 break;
785
786 default:
787 ret = obj_reloc_unhandled;
788 break;
789 }
790
791 return ret;
792}
793
794int arch_create_got(struct obj_file *f)
795{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000796 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000797 int i, n, offset = 0, gotneeded = 0;
798
799 n = ifile->root.header.e_shnum;
800 for (i = 0; i < n; ++i) {
801 struct obj_section *relsec, *symsec, *strsec;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000802#if defined(__sh__)
803 Elf32_Rela *rel, *relend;
804#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000805 Elf32_Rel *rel, *relend;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000806#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000807 Elf32_Sym *symtab;
808 const char *strtab;
809
810 relsec = ifile->root.sections[i];
811 if (relsec->header.sh_type != SHT_REL)
812 continue;
813
814 symsec = ifile->root.sections[relsec->header.sh_link];
815 strsec = ifile->root.sections[symsec->header.sh_link];
816
Eric Andersenfe4208f2000-09-24 03:44:29 +0000817
818#if defined(__sh__)
819 rel = (Elf32_Rela *) relsec->contents;
820 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rela));
821#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000822 rel = (Elf32_Rel *) relsec->contents;
823 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
Eric Andersenfe4208f2000-09-24 03:44:29 +0000824#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000825 symtab = (Elf32_Sym *) symsec->contents;
826 strtab = (const char *) strsec->contents;
827
828 for (; rel < relend; ++rel) {
829 Elf32_Sym *extsym;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000830 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 const char *name;
832
833 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000834#if defined(__sh__)
835 case R_SH_GOTPC:
836 case R_SH_GOTOFF:
837#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000838 case R_386_GOTPC:
839 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000840#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000841 gotneeded = 1;
842 default:
843 continue;
844
Eric Andersenfe4208f2000-09-24 03:44:29 +0000845#if defined(__sh__)
846 case R_SH_GOT32:
847#else
Eric Andersen9f16d612000-06-12 23:11:16 +0000848 case R_386_GOT32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000849#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000850 break;
851 }
852
853 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
854 if (extsym->st_name)
855 name = strtab + extsym->st_name;
856 else
857 name = f->sections[extsym->st_shndx]->name;
858 intsym =
Eric Andersenfe4208f2000-09-24 03:44:29 +0000859 (struct arch_symbol *) obj_find_symbol(&ifile->root, name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000860
861 if (!intsym->gotent.offset_done) {
862 intsym->gotent.offset_done = 1;
863 intsym->gotent.offset = offset;
864 offset += 4;
865 }
866 }
867 }
868
869 if (offset > 0 || gotneeded)
870 ifile->got =
871 obj_create_alloced_section(&ifile->root, ".got", 4, offset);
872
873 return 1;
874}
875
876int arch_init_module(struct obj_file *f, struct new_module *mod)
877{
878 return 1;
879}
880
881
882/*======================================================================*/
883
884/* Standard ELF hash function. */
885inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
886{
887 unsigned long h = 0;
888 unsigned long g;
889 unsigned char ch;
890
891 while (n > 0) {
892 ch = *name++;
893 h = (h << 4) + ch;
894 if ((g = (h & 0xf0000000)) != 0) {
895 h ^= g >> 24;
896 h &= ~g;
897 }
898 n--;
899 }
900 return h;
901}
902
903unsigned long obj_elf_hash(const char *name)
904{
905 return obj_elf_hash_n(name, strlen(name));
906}
907
908#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
909/* Get the kernel version in the canonical integer form. */
910
911static int get_kernel_version(char str[STRVERSIONLEN])
912{
913 struct utsname uts_info;
914 char *p, *q;
915 int a, b, c;
916
917 if (uname(&uts_info) < 0)
918 return -1;
919 strncpy(str, uts_info.release, STRVERSIONLEN);
920 p = uts_info.release;
921
922 a = strtoul(p, &p, 10);
923 if (*p != '.')
924 return -1;
925 b = strtoul(p + 1, &p, 10);
926 if (*p != '.')
927 return -1;
928 c = strtoul(p + 1, &q, 10);
929 if (p + 1 == q)
930 return -1;
931
932 return a << 16 | b << 8 | c;
933}
934
935/* String comparison for non-co-versioned kernel and module. */
936
937static int ncv_strcmp(const char *a, const char *b)
938{
939 size_t alen = strlen(a), blen = strlen(b);
940
941 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
942 return strncmp(a, b, alen);
943 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
944 return strncmp(a, b, blen);
945 else
946 return strcmp(a, b);
947}
948
949/* String hashing for non-co-versioned kernel and module. Here
950 we are simply forced to drop the crc from the hash. */
951
952static unsigned long ncv_symbol_hash(const char *str)
953{
954 size_t len = strlen(str);
955 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
956 len -= 10;
957 return obj_elf_hash_n(str, len);
958}
959
960void
961obj_set_symbol_compare(struct obj_file *f,
962 int (*cmp) (const char *, const char *),
963 unsigned long (*hash) (const char *))
964{
965 if (cmp)
966 f->symbol_cmp = cmp;
967 if (hash) {
968 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
969 int i;
970
971 f->symbol_hash = hash;
972
973 memcpy(tmptab, f->symtab, sizeof(tmptab));
974 memset(f->symtab, 0, sizeof(f->symtab));
975
976 for (i = 0; i < HASH_BUCKETS; ++i)
977 for (sym = tmptab[i]; sym; sym = next) {
978 unsigned long h = hash(sym->name) % HASH_BUCKETS;
979 next = sym->next;
980 sym->next = f->symtab[h];
981 f->symtab[h] = sym;
982 }
983 }
984}
985
986#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
987
988
989struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
990 unsigned long symidx, int info,
991 int secidx, ElfW(Addr) value,
992 unsigned long size)
993{
994 struct obj_symbol *sym;
995 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
996 int n_type = ELFW(ST_TYPE) (info);
997 int n_binding = ELFW(ST_BIND) (info);
998
999 for (sym = f->symtab[hash]; sym; sym = sym->next)
1000 if (f->symbol_cmp(sym->name, name) == 0) {
1001 int o_secidx = sym->secidx;
1002 int o_info = sym->info;
1003 int o_type = ELFW(ST_TYPE) (o_info);
1004 int o_binding = ELFW(ST_BIND) (o_info);
1005
1006 /* A redefinition! Is it legal? */
1007
1008 if (secidx == SHN_UNDEF)
1009 return sym;
1010 else if (o_secidx == SHN_UNDEF)
1011 goto found;
1012 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1013 /* Cope with local and global symbols of the same name
1014 in the same object file, as might have been created
1015 by ld -r. The only reason locals are now seen at this
1016 level at all is so that we can do semi-sensible things
1017 with parameters. */
1018
1019 struct obj_symbol *nsym, **p;
1020
1021 nsym = arch_new_symbol();
1022 nsym->next = sym->next;
1023 nsym->ksymidx = -1;
1024
1025 /* Excise the old (local) symbol from the hash chain. */
1026 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1027 continue;
1028 *p = sym = nsym;
1029 goto found;
1030 } else if (n_binding == STB_LOCAL) {
1031 /* Another symbol of the same name has already been defined.
1032 Just add this to the local table. */
1033 sym = arch_new_symbol();
1034 sym->next = NULL;
1035 sym->ksymidx = -1;
1036 f->local_symtab[symidx] = sym;
1037 goto found;
1038 } else if (n_binding == STB_WEAK)
1039 return sym;
1040 else if (o_binding == STB_WEAK)
1041 goto found;
1042 /* Don't unify COMMON symbols with object types the programmer
1043 doesn't expect. */
1044 else if (secidx == SHN_COMMON
1045 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1046 return sym;
1047 else if (o_secidx == SHN_COMMON
1048 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1049 goto found;
1050 else {
1051 /* Don't report an error if the symbol is coming from
1052 the kernel or some external module. */
1053 if (secidx <= SHN_HIRESERVE)
Matt Kraaid537a952000-07-14 01:51:25 +00001054 errorMsg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001055 return sym;
1056 }
1057 }
1058
1059 /* Completely new symbol. */
1060 sym = arch_new_symbol();
1061 sym->next = f->symtab[hash];
1062 f->symtab[hash] = sym;
1063 sym->ksymidx = -1;
1064
1065 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1066 f->local_symtab[symidx] = sym;
1067
1068 found:
1069 sym->name = name;
1070 sym->value = value;
1071 sym->size = size;
1072 sym->secidx = secidx;
1073 sym->info = info;
1074
1075 return sym;
1076}
1077
1078struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1079{
1080 struct obj_symbol *sym;
1081 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1082
1083 for (sym = f->symtab[hash]; sym; sym = sym->next)
1084 if (f->symbol_cmp(sym->name, name) == 0)
1085 return sym;
1086
1087 return NULL;
1088}
1089
1090ElfW(Addr)
1091 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1092{
1093 if (sym) {
1094 if (sym->secidx >= SHN_LORESERVE)
1095 return sym->value;
1096
1097 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1098 } else {
1099 /* As a special case, a NULL sym has value zero. */
1100 return 0;
1101 }
1102}
1103
1104struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1105{
1106 int i, n = f->header.e_shnum;
1107
1108 for (i = 0; i < n; ++i)
1109 if (strcmp(f->sections[i]->name, name) == 0)
1110 return f->sections[i];
1111
1112 return NULL;
1113}
1114
1115static int obj_load_order_prio(struct obj_section *a)
1116{
1117 unsigned long af, ac;
1118
1119 af = a->header.sh_flags;
1120
1121 ac = 0;
1122 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1123 strcmp(a->name + 5, ".init"))
1124 ac |= 32;
1125 if (af & SHF_ALLOC)
1126 ac |= 16;
1127 if (!(af & SHF_WRITE))
1128 ac |= 8;
1129 if (af & SHF_EXECINSTR)
1130 ac |= 4;
1131 if (a->header.sh_type != SHT_NOBITS)
1132 ac |= 2;
1133
1134 return ac;
1135}
1136
1137void
1138obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1139{
1140 struct obj_section **p;
1141 int prio = obj_load_order_prio(sec);
1142 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1143 if (obj_load_order_prio(*p) < prio)
1144 break;
1145 sec->load_next = *p;
1146 *p = sec;
1147}
1148
1149struct obj_section *obj_create_alloced_section(struct obj_file *f,
1150 const char *name,
1151 unsigned long align,
1152 unsigned long size)
1153{
1154 int newidx = f->header.e_shnum++;
1155 struct obj_section *sec;
1156
1157 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1158 f->sections[newidx] = sec = arch_new_section();
1159
1160 memset(sec, 0, sizeof(*sec));
1161 sec->header.sh_type = SHT_PROGBITS;
1162 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1163 sec->header.sh_size = size;
1164 sec->header.sh_addralign = align;
1165 sec->name = name;
1166 sec->idx = newidx;
1167 if (size)
1168 sec->contents = xmalloc(size);
1169
1170 obj_insert_section_load_order(f, sec);
1171
1172 return sec;
1173}
1174
1175struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1176 const char *name,
1177 unsigned long align,
1178 unsigned long size)
1179{
1180 int newidx = f->header.e_shnum++;
1181 struct obj_section *sec;
1182
1183 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1184 f->sections[newidx] = sec = arch_new_section();
1185
1186 memset(sec, 0, sizeof(*sec));
1187 sec->header.sh_type = SHT_PROGBITS;
1188 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1189 sec->header.sh_size = size;
1190 sec->header.sh_addralign = align;
1191 sec->name = name;
1192 sec->idx = newidx;
1193 if (size)
1194 sec->contents = xmalloc(size);
1195
1196 sec->load_next = f->load_order;
1197 f->load_order = sec;
1198 if (f->load_order_search_start == &f->load_order)
1199 f->load_order_search_start = &sec->load_next;
1200
1201 return sec;
1202}
1203
1204void *obj_extend_section(struct obj_section *sec, unsigned long more)
1205{
1206 unsigned long oldsize = sec->header.sh_size;
1207 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1208 return sec->contents + oldsize;
1209}
1210
1211
1212
1213/* Conditionally add the symbols from the given symbol set to the
1214 new module. */
1215
1216static int
1217add_symbols_from(
1218 struct obj_file *f,
1219 int idx, struct new_module_symbol *syms, size_t nsyms)
1220{
1221 struct new_module_symbol *s;
1222 size_t i;
1223 int used = 0;
1224
1225 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1226
1227 /* Only add symbols that are already marked external. If we
1228 override locals we may cause problems for argument initialization.
1229 We will also create a false dependency on the module. */
1230 struct obj_symbol *sym;
1231
1232 sym = obj_find_symbol(f, (char *) s->name);
1233 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1234 sym = obj_add_symbol(f, (char *) s->name, -1,
1235 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1236 idx, s->value, 0);
1237 /* Did our symbol just get installed? If so, mark the
1238 module as "used". */
1239 if (sym->secidx == idx)
1240 used = 1;
1241 }
1242 }
1243
1244 return used;
1245}
1246
1247static void add_kernel_symbols(struct obj_file *f)
1248{
1249 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001250 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001251
1252 /* Add module symbols first. */
1253
1254 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1255 if (m->nsyms
1256 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1257 m->nsyms)) m->used = 1, ++nused;
1258
1259 n_ext_modules_used = nused;
1260
1261 /* And finally the symbols from the kernel proper. */
1262
1263 if (nksyms)
1264 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1265}
1266
1267static char *get_modinfo_value(struct obj_file *f, const char *key)
1268{
1269 struct obj_section *sec;
1270 char *p, *v, *n, *ep;
1271 size_t klen = strlen(key);
1272
1273 sec = obj_find_section(f, ".modinfo");
1274 if (sec == NULL)
1275 return NULL;
1276 p = sec->contents;
1277 ep = p + sec->header.sh_size;
1278 while (p < ep) {
1279 v = strchr(p, '=');
1280 n = strchr(p, '\0');
1281 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001282 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001283 return v + 1;
1284 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001285 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001286 return n;
1287 }
1288 p = n + 1;
1289 }
1290
1291 return NULL;
1292}
1293
1294
1295/*======================================================================*/
1296/* Functions relating to module loading in pre 2.1 kernels. */
1297
1298static int
1299old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1300{
1301 while (argc > 0) {
1302 char *p, *q;
1303 struct obj_symbol *sym;
1304 int *loc;
1305
1306 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001307 if ((q = strchr(p, '=')) == NULL) {
1308 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001309 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001310 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001311 *q++ = '\0';
1312
1313 sym = obj_find_symbol(f, p);
1314
1315 /* Also check that the parameter was not resolved from the kernel. */
1316 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001317 errorMsg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001318 return 0;
1319 }
1320
1321 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1322
1323 /* Do C quoting if we begin with a ". */
1324 if (*q == '"') {
1325 char *r, *str;
1326
1327 str = alloca(strlen(q));
1328 for (r = str, q++; *q != '"'; ++q, ++r) {
1329 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001330 errorMsg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001331 return 0;
1332 } else if (*q == '\\')
1333 switch (*++q) {
1334 case 'a':
1335 *r = '\a';
1336 break;
1337 case 'b':
1338 *r = '\b';
1339 break;
1340 case 'e':
1341 *r = '\033';
1342 break;
1343 case 'f':
1344 *r = '\f';
1345 break;
1346 case 'n':
1347 *r = '\n';
1348 break;
1349 case 'r':
1350 *r = '\r';
1351 break;
1352 case 't':
1353 *r = '\t';
1354 break;
1355
1356 case '0':
1357 case '1':
1358 case '2':
1359 case '3':
1360 case '4':
1361 case '5':
1362 case '6':
1363 case '7':
1364 {
1365 int c = *q - '0';
1366 if (q[1] >= '0' && q[1] <= '7') {
1367 c = (c * 8) + *++q - '0';
1368 if (q[1] >= '0' && q[1] <= '7')
1369 c = (c * 8) + *++q - '0';
1370 }
1371 *r = c;
1372 }
1373 break;
1374
1375 default:
1376 *r = *q;
1377 break;
1378 } else
1379 *r = *q;
1380 }
1381 *r = '\0';
1382 obj_string_patch(f, sym->secidx, sym->value, str);
1383 } else if (*q >= '0' && *q <= '9') {
1384 do
1385 *loc++ = strtoul(q, &q, 0);
1386 while (*q++ == ',');
1387 } else {
1388 char *contents = f->sections[sym->secidx]->contents;
1389 char *loc = contents + sym->value;
1390 char *r; /* To search for commas */
1391
1392 /* Break the string with comas */
1393 while ((r = strchr(q, ',')) != (char *) NULL) {
1394 *r++ = '\0';
1395 obj_string_patch(f, sym->secidx, loc - contents, q);
1396 loc += sizeof(char *);
1397 q = r;
1398 }
1399
1400 /* last part */
1401 obj_string_patch(f, sym->secidx, loc - contents, q);
1402 }
1403
1404 argc--, argv++;
1405 }
1406
1407 return 1;
1408}
1409
1410#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1411static int old_is_module_checksummed(struct obj_file *f)
1412{
1413 return obj_find_symbol(f, "Using_Versions") != NULL;
1414}
1415/* Get the module's kernel version in the canonical integer form. */
1416
1417static int
1418old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1419{
1420 struct obj_symbol *sym;
1421 char *p, *q;
1422 int a, b, c;
1423
1424 sym = obj_find_symbol(f, "kernel_version");
1425 if (sym == NULL)
1426 return -1;
1427
1428 p = f->sections[sym->secidx]->contents + sym->value;
1429 strncpy(str, p, STRVERSIONLEN);
1430
1431 a = strtoul(p, &p, 10);
1432 if (*p != '.')
1433 return -1;
1434 b = strtoul(p + 1, &p, 10);
1435 if (*p != '.')
1436 return -1;
1437 c = strtoul(p + 1, &q, 10);
1438 if (p + 1 == q)
1439 return -1;
1440
1441 return a << 16 | b << 8 | c;
1442}
1443
1444#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1445
1446#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
1447
1448/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1449
Eric Andersen8c185f92000-09-22 00:38:07 +00001450static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001451{
1452 struct old_kernel_sym *ks, *k;
1453 struct new_module_symbol *s;
1454 struct external_module *mod;
1455 int nks, nms, nmod, i;
1456
1457 nks = get_kernel_syms(NULL);
1458 if (nks < 0) {
Matt Kraai207061a2000-10-23 18:03:46 +00001459 errorMsg("get_kernel_syms: %s: %s\n", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001460 return 0;
1461 }
1462
1463 ks = k = xmalloc(nks * sizeof(*ks));
1464
1465 if (get_kernel_syms(ks) != nks) {
1466 perror("inconsistency with get_kernel_syms -- is someone else "
1467 "playing with modules?");
1468 free(ks);
1469 return 0;
1470 }
1471
1472 /* Collect the module information. */
1473
1474 mod = NULL;
1475 nmod = -1;
1476
1477 while (k->name[0] == '#' && k->name[1]) {
1478 struct old_kernel_sym *k2;
1479 struct new_module_symbol *s;
1480
1481 /* Find out how many symbols this module has. */
1482 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1483 continue;
1484 nms = k2 - k - 1;
1485
1486 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1487 mod[nmod].name = k->name + 1;
1488 mod[nmod].addr = k->value;
1489 mod[nmod].used = 0;
1490 mod[nmod].nsyms = nms;
1491 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1492
1493 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1494 s->name = (unsigned long) k->name;
1495 s->value = k->value;
1496 }
1497
1498 k = k2;
1499 }
1500
1501 ext_modules = mod;
1502 n_ext_modules = nmod + 1;
1503
1504 /* Now collect the symbols for the kernel proper. */
1505
1506 if (k->name[0] == '#')
1507 ++k;
1508
1509 nksyms = nms = nks - (k - ks);
1510 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1511
1512 for (i = 0; i < nms; ++i, ++s, ++k) {
1513 s->name = (unsigned long) k->name;
1514 s->value = k->value;
1515 }
1516
1517 return 1;
1518}
1519
1520/* Return the kernel symbol checksum version, or zero if not used. */
1521
1522static int old_is_kernel_checksummed(void)
1523{
1524 /* Using_Versions is the first symbol. */
1525 if (nksyms > 0
1526 && strcmp((char *) ksyms[0].name,
1527 "Using_Versions") == 0) return ksyms[0].value;
1528 else
1529 return 0;
1530}
1531
1532
1533static int old_create_mod_use_count(struct obj_file *f)
1534{
1535 struct obj_section *sec;
1536
1537 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1538 sizeof(long));
1539
1540 obj_add_symbol(f, "mod_use_count_", -1,
1541 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1542 sizeof(long));
1543
1544 return 1;
1545}
1546
1547static int
1548old_init_module(const char *m_name, struct obj_file *f,
1549 unsigned long m_size)
1550{
1551 char *image;
1552 struct old_mod_routines routines;
1553 struct old_symbol_table *symtab;
1554 int ret;
1555
1556 /* Create the symbol table */
1557 {
1558 int nsyms = 0, strsize = 0, total;
1559
1560 /* Size things first... */
1561 if (flag_export) {
1562 int i;
1563 for (i = 0; i < HASH_BUCKETS; ++i) {
1564 struct obj_symbol *sym;
1565 for (sym = f->symtab[i]; sym; sym = sym->next)
1566 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1567 && sym->secidx <= SHN_HIRESERVE)
1568 {
1569 sym->ksymidx = nsyms++;
1570 strsize += strlen(sym->name) + 1;
1571 }
1572 }
1573 }
1574
1575 total = (sizeof(struct old_symbol_table)
1576 + nsyms * sizeof(struct old_module_symbol)
1577 + n_ext_modules_used * sizeof(struct old_module_ref)
1578 + strsize);
1579 symtab = xmalloc(total);
1580 symtab->size = total;
1581 symtab->n_symbols = nsyms;
1582 symtab->n_refs = n_ext_modules_used;
1583
1584 if (flag_export && nsyms) {
1585 struct old_module_symbol *ksym;
1586 char *str;
1587 int i;
1588
1589 ksym = symtab->symbol;
1590 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1591 + n_ext_modules_used * sizeof(struct old_module_ref));
1592
1593 for (i = 0; i < HASH_BUCKETS; ++i) {
1594 struct obj_symbol *sym;
1595 for (sym = f->symtab[i]; sym; sym = sym->next)
1596 if (sym->ksymidx >= 0) {
1597 ksym->addr = obj_symbol_final_value(f, sym);
1598 ksym->name =
1599 (unsigned long) str - (unsigned long) symtab;
1600
1601 str = stpcpy(str, sym->name) + 1;
1602 ksym++;
1603 }
1604 }
1605 }
1606
1607 if (n_ext_modules_used) {
1608 struct old_module_ref *ref;
1609 int i;
1610
1611 ref = (struct old_module_ref *)
1612 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1613
1614 for (i = 0; i < n_ext_modules; ++i)
1615 if (ext_modules[i].used)
1616 ref++->module = ext_modules[i].addr;
1617 }
1618 }
1619
1620 /* Fill in routines. */
1621
1622 routines.init =
1623 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1624 routines.cleanup =
1625 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1626
1627 /* Whew! All of the initialization is complete. Collect the final
1628 module image and give it to the kernel. */
1629
1630 image = xmalloc(m_size);
1631 obj_create_image(f, image);
1632
1633 /* image holds the complete relocated module, accounting correctly for
1634 mod_use_count. However the old module kernel support assume that
1635 it is receiving something which does not contain mod_use_count. */
1636 ret = old_sys_init_module(m_name, image + sizeof(long),
1637 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1638 : 0), &routines, symtab);
1639 if (ret)
Matt Kraai207061a2000-10-23 18:03:46 +00001640 errorMsg("init_module: %s: %s\n", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001641
1642 free(image);
1643 free(symtab);
1644
1645 return ret == 0;
1646}
1647
1648#else
1649
1650#define old_create_mod_use_count(x) TRUE
1651#define old_init_module(x, y, z) TRUE
1652
1653#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
1654
1655
1656
1657/*======================================================================*/
1658/* Functions relating to module loading after 2.1.18. */
1659
1660static int
1661new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1662{
1663 while (argc > 0) {
1664 char *p, *q, *key;
1665 struct obj_symbol *sym;
1666 char *contents, *loc;
1667 int min, max, n;
1668
1669 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001670 if ((q = strchr(p, '=')) == NULL) {
1671 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001672 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001673 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001674
1675 key = alloca(q - p + 6);
1676 memcpy(key, "parm_", 5);
1677 memcpy(key + 5, p, q - p);
1678 key[q - p + 5] = 0;
1679
1680 p = get_modinfo_value(f, key);
1681 key += 5;
1682 if (p == NULL) {
Matt Kraaid537a952000-07-14 01:51:25 +00001683 errorMsg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001684 return 0;
1685 }
1686
1687 sym = obj_find_symbol(f, key);
1688
1689 /* Also check that the parameter was not resolved from the kernel. */
1690 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001691 errorMsg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001692 return 0;
1693 }
1694
1695 if (isdigit(*p)) {
1696 min = strtoul(p, &p, 10);
1697 if (*p == '-')
1698 max = strtoul(p + 1, &p, 10);
1699 else
1700 max = min;
1701 } else
1702 min = max = 1;
1703
1704 contents = f->sections[sym->secidx]->contents;
1705 loc = contents + sym->value;
1706 n = (*++q != '\0');
1707
1708 while (1) {
1709 if ((*p == 's') || (*p == 'c')) {
1710 char *str;
1711
1712 /* Do C quoting if we begin with a ", else slurp the lot. */
1713 if (*q == '"') {
1714 char *r;
1715
1716 str = alloca(strlen(q));
1717 for (r = str, q++; *q != '"'; ++q, ++r) {
1718 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001719 errorMsg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001720 key);
1721 return 0;
1722 } else if (*q == '\\')
1723 switch (*++q) {
1724 case 'a':
1725 *r = '\a';
1726 break;
1727 case 'b':
1728 *r = '\b';
1729 break;
1730 case 'e':
1731 *r = '\033';
1732 break;
1733 case 'f':
1734 *r = '\f';
1735 break;
1736 case 'n':
1737 *r = '\n';
1738 break;
1739 case 'r':
1740 *r = '\r';
1741 break;
1742 case 't':
1743 *r = '\t';
1744 break;
1745
1746 case '0':
1747 case '1':
1748 case '2':
1749 case '3':
1750 case '4':
1751 case '5':
1752 case '6':
1753 case '7':
1754 {
1755 int c = *q - '0';
1756 if (q[1] >= '0' && q[1] <= '7') {
1757 c = (c * 8) + *++q - '0';
1758 if (q[1] >= '0' && q[1] <= '7')
1759 c = (c * 8) + *++q - '0';
1760 }
1761 *r = c;
1762 }
1763 break;
1764
1765 default:
1766 *r = *q;
1767 break;
1768 } else
1769 *r = *q;
1770 }
1771 *r = '\0';
1772 ++q;
1773 } else {
1774 char *r;
1775
1776 /* In this case, the string is not quoted. We will break
1777 it using the coma (like for ints). If the user wants to
1778 include comas in a string, he just has to quote it */
1779
1780 /* Search the next coma */
1781 r = strchr(q, ',');
1782
1783 /* Found ? */
1784 if (r != (char *) NULL) {
1785 /* Recopy the current field */
1786 str = alloca(r - q + 1);
1787 memcpy(str, q, r - q);
1788
1789 /* I don't know if it is usefull, as the previous case
1790 doesn't null terminate the string ??? */
1791 str[r - q] = '\0';
1792
1793 /* Keep next fields */
1794 q = r;
1795 } else {
1796 /* last string */
1797 str = q;
1798 q = "";
1799 }
1800 }
1801
1802 if (*p == 's') {
1803 /* Normal string */
1804 obj_string_patch(f, sym->secidx, loc - contents, str);
1805 loc += tgt_sizeof_char_p;
1806 } else {
1807 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001808 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001809
1810 /* Get the size of each member */
1811 /* Probably we should do that outside the loop ? */
1812 if (!isdigit(*(p + 1))) {
Matt Kraaid537a952000-07-14 01:51:25 +00001813 errorMsg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001814 " the maximum size\n", key);
1815 return 0;
1816 }
1817 charssize = strtoul(p + 1, (char **) NULL, 10);
1818
1819 /* Check length */
1820 if (strlen(str) >= charssize) {
Matt Kraaid537a952000-07-14 01:51:25 +00001821 errorMsg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001822 charssize - 1);
1823 return 0;
1824 }
1825
1826 /* Copy to location */
1827 strcpy((char *) loc, str);
1828 loc += charssize;
1829 }
1830 } else {
1831 long v = strtoul(q, &q, 0);
1832 switch (*p) {
1833 case 'b':
1834 *loc++ = v;
1835 break;
1836 case 'h':
1837 *(short *) loc = v;
1838 loc += tgt_sizeof_short;
1839 break;
1840 case 'i':
1841 *(int *) loc = v;
1842 loc += tgt_sizeof_int;
1843 break;
1844 case 'l':
1845 *(long *) loc = v;
1846 loc += tgt_sizeof_long;
1847 break;
1848
1849 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001850 errorMsg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001851 return 0;
1852 }
1853 }
1854
1855 retry_end_of_value:
1856 switch (*q) {
1857 case '\0':
1858 goto end_of_arg;
1859
1860 case ' ':
1861 case '\t':
1862 case '\n':
1863 case '\r':
1864 ++q;
1865 goto retry_end_of_value;
1866
1867 case ',':
1868 if (++n > max) {
Matt Kraaid537a952000-07-14 01:51:25 +00001869 errorMsg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001870 return 0;
1871 }
1872 ++q;
1873 break;
1874
1875 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001876 errorMsg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001877 return 0;
1878 }
1879 }
1880
1881 end_of_arg:
1882 if (n < min) {
Matt Kraaid537a952000-07-14 01:51:25 +00001883 errorMsg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001884 return 0;
1885 }
1886
1887 argc--, argv++;
1888 }
1889
1890 return 1;
1891}
1892
1893#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1894static int new_is_module_checksummed(struct obj_file *f)
1895{
1896 const char *p = get_modinfo_value(f, "using_checksums");
1897 if (p)
1898 return atoi(p);
1899 else
1900 return 0;
1901}
1902
1903/* Get the module's kernel version in the canonical integer form. */
1904
1905static int
1906new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1907{
1908 char *p, *q;
1909 int a, b, c;
1910
1911 p = get_modinfo_value(f, "kernel_version");
1912 if (p == NULL)
1913 return -1;
1914 strncpy(str, p, STRVERSIONLEN);
1915
1916 a = strtoul(p, &p, 10);
1917 if (*p != '.')
1918 return -1;
1919 b = strtoul(p + 1, &p, 10);
1920 if (*p != '.')
1921 return -1;
1922 c = strtoul(p + 1, &q, 10);
1923 if (p + 1 == q)
1924 return -1;
1925
1926 return a << 16 | b << 8 | c;
1927}
1928
1929#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1930
1931
1932#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
1933
1934/* Fetch the loaded modules, and all currently exported symbols. */
1935
1936static int new_get_kernel_symbols(void)
1937{
1938 char *module_names, *mn;
1939 struct external_module *modules, *m;
1940 struct new_module_symbol *syms, *s;
1941 size_t ret, bufsize, nmod, nsyms, i, j;
1942
1943 /* Collect the loaded modules. */
1944
1945 module_names = xmalloc(bufsize = 256);
1946 retry_modules_load:
1947 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
1948 if (errno == ENOSPC) {
1949 module_names = xrealloc(module_names, bufsize = ret);
1950 goto retry_modules_load;
1951 }
Matt Kraai207061a2000-10-23 18:03:46 +00001952 errorMsg("QM_MODULES: %s\n", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001953 return 0;
1954 }
1955
1956 n_ext_modules = nmod = ret;
1957 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
1958 memset(modules, 0, nmod * sizeof(*modules));
1959
1960 /* Collect the modules' symbols. */
1961
1962 for (i = 0, mn = module_names, m = modules;
1963 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
1964 struct new_module_info info;
1965
1966 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
1967 if (errno == ENOENT) {
1968 /* The module was removed out from underneath us. */
1969 continue;
1970 }
Matt Kraai207061a2000-10-23 18:03:46 +00001971 errorMsg("query_module: QM_INFO: %s: %s\n", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001972 return 0;
1973 }
1974
1975 syms = xmalloc(bufsize = 1024);
1976 retry_mod_sym_load:
1977 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
1978 switch (errno) {
1979 case ENOSPC:
1980 syms = xrealloc(syms, bufsize = ret);
1981 goto retry_mod_sym_load;
1982 case ENOENT:
1983 /* The module was removed out from underneath us. */
1984 continue;
1985 default:
Matt Kraai207061a2000-10-23 18:03:46 +00001986 errorMsg("query_module: QM_SYMBOLS: %s: %s\n", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001987 return 0;
1988 }
1989 }
1990 nsyms = ret;
1991
1992 m->name = mn;
1993 m->addr = info.addr;
1994 m->nsyms = nsyms;
1995 m->syms = syms;
1996
1997 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1998 s->name += (unsigned long) syms;
1999 }
2000 }
2001
2002 /* Collect the kernel's symbols. */
2003
2004 syms = xmalloc(bufsize = 16 * 1024);
2005 retry_kern_sym_load:
2006 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2007 if (errno == ENOSPC) {
2008 syms = xrealloc(syms, bufsize = ret);
2009 goto retry_kern_sym_load;
2010 }
Matt Kraai207061a2000-10-23 18:03:46 +00002011 errorMsg("kernel: QM_SYMBOLS: %s\n", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002012 return 0;
2013 }
2014 nksyms = nsyms = ret;
2015 ksyms = syms;
2016
2017 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2018 s->name += (unsigned long) syms;
2019 }
2020 return 1;
2021}
2022
2023
2024/* Return the kernel symbol checksum version, or zero if not used. */
2025
2026static int new_is_kernel_checksummed(void)
2027{
2028 struct new_module_symbol *s;
2029 size_t i;
2030
2031 /* Using_Versions is not the first symbol, but it should be in there. */
2032
2033 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2034 if (strcmp((char *) s->name, "Using_Versions") == 0)
2035 return s->value;
2036
2037 return 0;
2038}
2039
2040
2041static int new_create_this_module(struct obj_file *f, const char *m_name)
2042{
2043 struct obj_section *sec;
2044
2045 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2046 sizeof(struct new_module));
2047 memset(sec->contents, 0, sizeof(struct new_module));
2048
2049 obj_add_symbol(f, "__this_module", -1,
2050 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2051 sizeof(struct new_module));
2052
2053 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2054 m_name);
2055
2056 return 1;
2057}
2058
2059
2060static int new_create_module_ksymtab(struct obj_file *f)
2061{
2062 struct obj_section *sec;
2063 int i;
2064
2065 /* We must always add the module references. */
2066
2067 if (n_ext_modules_used) {
2068 struct new_module_ref *dep;
2069 struct obj_symbol *tm;
2070
2071 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2072 (sizeof(struct new_module_ref)
2073 * n_ext_modules_used));
2074 if (!sec)
2075 return 0;
2076
2077 tm = obj_find_symbol(f, "__this_module");
2078 dep = (struct new_module_ref *) sec->contents;
2079 for (i = 0; i < n_ext_modules; ++i)
2080 if (ext_modules[i].used) {
2081 dep->dep = ext_modules[i].addr;
2082 obj_symbol_patch(f, sec->idx,
2083 (char *) &dep->ref - sec->contents, tm);
2084 dep->next_ref = 0;
2085 ++dep;
2086 }
2087 }
2088
2089 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2090 size_t nsyms;
2091 int *loaded;
2092
2093 sec =
2094 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2095 0);
2096
2097 /* We don't want to export symbols residing in sections that
2098 aren't loaded. There are a number of these created so that
2099 we make sure certain module options don't appear twice. */
2100
2101 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2102 while (--i >= 0)
2103 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2104
2105 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2106 struct obj_symbol *sym;
2107 for (sym = f->symtab[i]; sym; sym = sym->next)
2108 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2109 && sym->secidx <= SHN_HIRESERVE
2110 && (sym->secidx >= SHN_LORESERVE
2111 || loaded[sym->secidx])) {
2112 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2113
2114 obj_symbol_patch(f, sec->idx, ofs, sym);
2115 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2116 sym->name);
2117
2118 nsyms++;
2119 }
2120 }
2121
2122 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2123 }
2124
2125 return 1;
2126}
2127
2128
2129static int
2130new_init_module(const char *m_name, struct obj_file *f,
2131 unsigned long m_size)
2132{
2133 struct new_module *module;
2134 struct obj_section *sec;
2135 void *image;
2136 int ret;
2137 tgt_long m_addr;
2138
2139 sec = obj_find_section(f, ".this");
2140 module = (struct new_module *) sec->contents;
2141 m_addr = sec->header.sh_addr;
2142
2143 module->size_of_struct = sizeof(*module);
2144 module->size = m_size;
2145 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2146
2147 sec = obj_find_section(f, "__ksymtab");
2148 if (sec && sec->header.sh_size) {
2149 module->syms = sec->header.sh_addr;
2150 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2151 }
2152
2153 if (n_ext_modules_used) {
2154 sec = obj_find_section(f, ".kmodtab");
2155 module->deps = sec->header.sh_addr;
2156 module->ndeps = n_ext_modules_used;
2157 }
2158
2159 module->init =
2160 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2161 module->cleanup =
2162 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2163
2164 sec = obj_find_section(f, "__ex_table");
2165 if (sec) {
2166 module->ex_table_start = sec->header.sh_addr;
2167 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2168 }
2169
2170 sec = obj_find_section(f, ".text.init");
2171 if (sec) {
2172 module->runsize = sec->header.sh_addr - m_addr;
2173 }
2174 sec = obj_find_section(f, ".data.init");
2175 if (sec) {
2176 if (!module->runsize ||
2177 module->runsize > sec->header.sh_addr - m_addr)
2178 module->runsize = sec->header.sh_addr - m_addr;
2179 }
2180
2181 if (!arch_init_module(f, module))
2182 return 0;
2183
2184 /* Whew! All of the initialization is complete. Collect the final
2185 module image and give it to the kernel. */
2186
2187 image = xmalloc(m_size);
2188 obj_create_image(f, image);
2189
2190 ret = new_sys_init_module(m_name, (struct new_module *) image);
2191 if (ret)
Matt Kraai207061a2000-10-23 18:03:46 +00002192 errorMsg("init_module: %s: %s\n", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002193
2194 free(image);
2195
2196 return ret == 0;
2197}
2198
2199#else
2200
2201#define new_init_module(x, y, z) TRUE
2202#define new_create_this_module(x, y) 0
2203#define new_create_module_ksymtab(x)
2204
2205#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
2206
2207
2208/*======================================================================*/
2209
2210int
2211obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2212 const char *string)
2213{
2214 struct obj_string_patch *p;
2215 struct obj_section *strsec;
2216 size_t len = strlen(string) + 1;
2217 char *loc;
2218
2219 p = xmalloc(sizeof(*p));
2220 p->next = f->string_patches;
2221 p->reloc_secidx = secidx;
2222 p->reloc_offset = offset;
2223 f->string_patches = p;
2224
2225 strsec = obj_find_section(f, ".kstrtab");
2226 if (strsec == NULL) {
2227 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2228 p->string_offset = 0;
2229 loc = strsec->contents;
2230 } else {
2231 p->string_offset = strsec->header.sh_size;
2232 loc = obj_extend_section(strsec, len);
2233 }
2234 memcpy(loc, string, len);
2235
2236 return 1;
2237}
2238
2239int
2240obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2241 struct obj_symbol *sym)
2242{
2243 struct obj_symbol_patch *p;
2244
2245 p = xmalloc(sizeof(*p));
2246 p->next = f->symbol_patches;
2247 p->reloc_secidx = secidx;
2248 p->reloc_offset = offset;
2249 p->sym = sym;
2250 f->symbol_patches = p;
2251
2252 return 1;
2253}
2254
2255int obj_check_undefineds(struct obj_file *f)
2256{
2257 unsigned long i;
2258 int ret = 1;
2259
2260 for (i = 0; i < HASH_BUCKETS; ++i) {
2261 struct obj_symbol *sym;
2262 for (sym = f->symtab[i]; sym; sym = sym->next)
2263 if (sym->secidx == SHN_UNDEF) {
2264 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2265 sym->secidx = SHN_ABS;
2266 sym->value = 0;
2267 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002268 errorMsg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002269 ret = 0;
2270 }
2271 }
2272 }
2273
2274 return ret;
2275}
2276
2277void obj_allocate_commons(struct obj_file *f)
2278{
2279 struct common_entry {
2280 struct common_entry *next;
2281 struct obj_symbol *sym;
2282 } *common_head = NULL;
2283
2284 unsigned long i;
2285
2286 for (i = 0; i < HASH_BUCKETS; ++i) {
2287 struct obj_symbol *sym;
2288 for (sym = f->symtab[i]; sym; sym = sym->next)
2289 if (sym->secidx == SHN_COMMON) {
2290 /* Collect all COMMON symbols and sort them by size so as to
2291 minimize space wasted by alignment requirements. */
2292 {
2293 struct common_entry **p, *n;
2294 for (p = &common_head; *p; p = &(*p)->next)
2295 if (sym->size <= (*p)->sym->size)
2296 break;
2297
2298 n = alloca(sizeof(*n));
2299 n->next = *p;
2300 n->sym = sym;
2301 *p = n;
2302 }
2303 }
2304 }
2305
2306 for (i = 1; i < f->local_symtab_size; ++i) {
2307 struct obj_symbol *sym = f->local_symtab[i];
2308 if (sym && sym->secidx == SHN_COMMON) {
2309 struct common_entry **p, *n;
2310 for (p = &common_head; *p; p = &(*p)->next)
2311 if (sym == (*p)->sym)
2312 break;
2313 else if (sym->size < (*p)->sym->size) {
2314 n = alloca(sizeof(*n));
2315 n->next = *p;
2316 n->sym = sym;
2317 *p = n;
2318 break;
2319 }
2320 }
2321 }
2322
2323 if (common_head) {
2324 /* Find the bss section. */
2325 for (i = 0; i < f->header.e_shnum; ++i)
2326 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2327 break;
2328
2329 /* If for some reason there hadn't been one, create one. */
2330 if (i == f->header.e_shnum) {
2331 struct obj_section *sec;
2332
2333 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2334 f->sections[i] = sec = arch_new_section();
2335 f->header.e_shnum = i + 1;
2336
2337 memset(sec, 0, sizeof(*sec));
2338 sec->header.sh_type = SHT_PROGBITS;
2339 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2340 sec->name = ".bss";
2341 sec->idx = i;
2342 }
2343
2344 /* Allocate the COMMONS. */
2345 {
2346 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2347 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2348 struct common_entry *c;
2349
2350 for (c = common_head; c; c = c->next) {
2351 ElfW(Addr) align = c->sym->value;
2352
2353 if (align > max_align)
2354 max_align = align;
2355 if (bss_size & (align - 1))
2356 bss_size = (bss_size | (align - 1)) + 1;
2357
2358 c->sym->secidx = i;
2359 c->sym->value = bss_size;
2360
2361 bss_size += c->sym->size;
2362 }
2363
2364 f->sections[i]->header.sh_size = bss_size;
2365 f->sections[i]->header.sh_addralign = max_align;
2366 }
2367 }
2368
2369 /* For the sake of patch relocation and parameter initialization,
2370 allocate zeroed data for NOBITS sections now. Note that after
2371 this we cannot assume NOBITS are really empty. */
2372 for (i = 0; i < f->header.e_shnum; ++i) {
2373 struct obj_section *s = f->sections[i];
2374 if (s->header.sh_type == SHT_NOBITS) {
2375 s->contents = memset(xmalloc(s->header.sh_size),
2376 0, s->header.sh_size);
2377 s->header.sh_type = SHT_PROGBITS;
2378 }
2379 }
2380}
2381
2382unsigned long obj_load_size(struct obj_file *f)
2383{
2384 unsigned long dot = 0;
2385 struct obj_section *sec;
2386
2387 /* Finalize the positions of the sections relative to one another. */
2388
2389 for (sec = f->load_order; sec; sec = sec->load_next) {
2390 ElfW(Addr) align;
2391
2392 align = sec->header.sh_addralign;
2393 if (align && (dot & (align - 1)))
2394 dot = (dot | (align - 1)) + 1;
2395
2396 sec->header.sh_addr = dot;
2397 dot += sec->header.sh_size;
2398 }
2399
2400 return dot;
2401}
2402
2403int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2404{
2405 int i, n = f->header.e_shnum;
2406 int ret = 1;
2407
2408 /* Finalize the addresses of the sections. */
2409
2410 f->baseaddr = base;
2411 for (i = 0; i < n; ++i)
2412 f->sections[i]->header.sh_addr += base;
2413
2414 /* And iterate over all of the relocations. */
2415
2416 for (i = 0; i < n; ++i) {
2417 struct obj_section *relsec, *symsec, *targsec, *strsec;
2418 ElfW(RelM) * rel, *relend;
2419 ElfW(Sym) * symtab;
2420 const char *strtab;
2421
2422 relsec = f->sections[i];
2423 if (relsec->header.sh_type != SHT_RELM)
2424 continue;
2425
2426 symsec = f->sections[relsec->header.sh_link];
2427 targsec = f->sections[relsec->header.sh_info];
2428 strsec = f->sections[symsec->header.sh_link];
2429
2430 rel = (ElfW(RelM) *) relsec->contents;
2431 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2432 symtab = (ElfW(Sym) *) symsec->contents;
2433 strtab = (const char *) strsec->contents;
2434
2435 for (; rel < relend; ++rel) {
2436 ElfW(Addr) value = 0;
2437 struct obj_symbol *intsym = NULL;
2438 unsigned long symndx;
2439 ElfW(Sym) * extsym = 0;
2440 const char *errmsg;
2441
2442 /* Attempt to find a value to use for this relocation. */
2443
2444 symndx = ELFW(R_SYM) (rel->r_info);
2445 if (symndx) {
2446 /* Note we've already checked for undefined symbols. */
2447
2448 extsym = &symtab[symndx];
2449 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2450 /* Local symbols we look up in the local table to be sure
2451 we get the one that is really intended. */
2452 intsym = f->local_symtab[symndx];
2453 } else {
2454 /* Others we look up in the hash table. */
2455 const char *name;
2456 if (extsym->st_name)
2457 name = strtab + extsym->st_name;
2458 else
2459 name = f->sections[extsym->st_shndx]->name;
2460 intsym = obj_find_symbol(f, name);
2461 }
2462
2463 value = obj_symbol_final_value(f, intsym);
2464 intsym->referenced = 1;
2465 }
2466#if SHT_RELM == SHT_RELA
2467#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2468 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2469 if (!extsym || !extsym->st_name ||
2470 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2471#endif
2472 value += rel->r_addend;
2473#endif
2474
2475 /* Do it! */
2476 switch (arch_apply_relocation
2477 (f, targsec, symsec, intsym, rel, value)) {
2478 case obj_reloc_ok:
2479 break;
2480
2481 case obj_reloc_overflow:
2482 errmsg = "Relocation overflow";
2483 goto bad_reloc;
2484 case obj_reloc_dangerous:
2485 errmsg = "Dangerous relocation";
2486 goto bad_reloc;
2487 case obj_reloc_unhandled:
2488 errmsg = "Unhandled relocation";
2489 bad_reloc:
2490 if (extsym) {
Matt Kraaid537a952000-07-14 01:51:25 +00002491 errorMsg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002492 (long) ELFW(R_TYPE) (rel->r_info),
2493 strtab + extsym->st_name);
2494 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002495 errorMsg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002496 (long) ELFW(R_TYPE) (rel->r_info));
2497 }
2498 ret = 0;
2499 break;
2500 }
2501 }
2502 }
2503
2504 /* Finally, take care of the patches. */
2505
2506 if (f->string_patches) {
2507 struct obj_string_patch *p;
2508 struct obj_section *strsec;
2509 ElfW(Addr) strsec_base;
2510 strsec = obj_find_section(f, ".kstrtab");
2511 strsec_base = strsec->header.sh_addr;
2512
2513 for (p = f->string_patches; p; p = p->next) {
2514 struct obj_section *targsec = f->sections[p->reloc_secidx];
2515 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2516 = strsec_base + p->string_offset;
2517 }
2518 }
2519
2520 if (f->symbol_patches) {
2521 struct obj_symbol_patch *p;
2522
2523 for (p = f->symbol_patches; p; p = p->next) {
2524 struct obj_section *targsec = f->sections[p->reloc_secidx];
2525 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2526 = obj_symbol_final_value(f, p->sym);
2527 }
2528 }
2529
2530 return ret;
2531}
2532
2533int obj_create_image(struct obj_file *f, char *image)
2534{
2535 struct obj_section *sec;
2536 ElfW(Addr) base = f->baseaddr;
2537
2538 for (sec = f->load_order; sec; sec = sec->load_next) {
2539 char *secimg;
2540
2541 if (sec->header.sh_size == 0)
2542 continue;
2543
2544 secimg = image + (sec->header.sh_addr - base);
2545
2546 /* Note that we allocated data for NOBITS sections earlier. */
2547 memcpy(secimg, sec->contents, sec->header.sh_size);
2548 }
2549
2550 return 1;
2551}
2552
2553/*======================================================================*/
2554
2555struct obj_file *obj_load(FILE * fp)
2556{
2557 struct obj_file *f;
2558 ElfW(Shdr) * section_headers;
2559 int shnum, i;
2560 char *shstrtab;
2561
2562 /* Read the file header. */
2563
2564 f = arch_new_file();
2565 memset(f, 0, sizeof(*f));
2566 f->symbol_cmp = strcmp;
2567 f->symbol_hash = obj_elf_hash;
2568 f->load_order_search_start = &f->load_order;
2569
2570 fseek(fp, 0, SEEK_SET);
2571 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai207061a2000-10-23 18:03:46 +00002572 errorMsg("error reading ELF header: %s\n", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002573 return NULL;
2574 }
2575
2576 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2577 || f->header.e_ident[EI_MAG1] != ELFMAG1
2578 || f->header.e_ident[EI_MAG2] != ELFMAG2
2579 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaid537a952000-07-14 01:51:25 +00002580 errorMsg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002581 return NULL;
2582 }
2583 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2584 || f->header.e_ident[EI_DATA] != ELFDATAM
2585 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2586 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaid537a952000-07-14 01:51:25 +00002587 errorMsg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002588 return NULL;
2589 }
2590 if (f->header.e_type != ET_REL) {
Matt Kraaid537a952000-07-14 01:51:25 +00002591 errorMsg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002592 return NULL;
2593 }
2594
2595 /* Read the section headers. */
2596
2597 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002598 errorMsg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002599 (unsigned long) f->header.e_shentsize,
2600 (unsigned long) sizeof(ElfW(Shdr)));
2601 return NULL;
2602 }
2603
2604 shnum = f->header.e_shnum;
2605 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2606 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2607
2608 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2609 fseek(fp, f->header.e_shoff, SEEK_SET);
2610 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai207061a2000-10-23 18:03:46 +00002611 errorMsg("error reading ELF section headers: %s\n", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002612 return NULL;
2613 }
2614
2615 /* Read the section data. */
2616
2617 for (i = 0; i < shnum; ++i) {
2618 struct obj_section *sec;
2619
2620 f->sections[i] = sec = arch_new_section();
2621 memset(sec, 0, sizeof(*sec));
2622
2623 sec->header = section_headers[i];
2624 sec->idx = i;
2625
2626 switch (sec->header.sh_type) {
2627 case SHT_NULL:
2628 case SHT_NOTE:
2629 case SHT_NOBITS:
2630 /* ignore */
2631 break;
2632
2633 case SHT_PROGBITS:
2634 case SHT_SYMTAB:
2635 case SHT_STRTAB:
2636 case SHT_RELM:
2637 if (sec->header.sh_size > 0) {
2638 sec->contents = xmalloc(sec->header.sh_size);
2639 fseek(fp, sec->header.sh_offset, SEEK_SET);
2640 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai207061a2000-10-23 18:03:46 +00002641 errorMsg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002642 return NULL;
2643 }
2644 } else {
2645 sec->contents = NULL;
2646 }
2647 break;
2648
2649#if SHT_RELM == SHT_REL
2650 case SHT_RELA:
Matt Kraaid537a952000-07-14 01:51:25 +00002651 errorMsg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002652 return NULL;
2653#else
2654 case SHT_REL:
Matt Kraaid537a952000-07-14 01:51:25 +00002655 errorMsg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002656 return NULL;
2657#endif
2658
2659 default:
2660 if (sec->header.sh_type >= SHT_LOPROC) {
2661 /* Assume processor specific section types are debug
2662 info and can safely be ignored. If this is ever not
2663 the case (Hello MIPS?), don't put ifdefs here but
2664 create an arch_load_proc_section(). */
2665 break;
2666 }
2667
Matt Kraaid537a952000-07-14 01:51:25 +00002668 errorMsg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002669 (long) sec->header.sh_type);
2670 return NULL;
2671 }
2672 }
2673
2674 /* Do what sort of interpretation as needed by each section. */
2675
2676 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2677
2678 for (i = 0; i < shnum; ++i) {
2679 struct obj_section *sec = f->sections[i];
2680 sec->name = shstrtab + sec->header.sh_name;
2681 }
2682
2683 for (i = 0; i < shnum; ++i) {
2684 struct obj_section *sec = f->sections[i];
2685
2686 if (sec->header.sh_flags & SHF_ALLOC)
2687 obj_insert_section_load_order(f, sec);
2688
2689 switch (sec->header.sh_type) {
2690 case SHT_SYMTAB:
2691 {
2692 unsigned long nsym, j;
2693 char *strtab;
2694 ElfW(Sym) * sym;
2695
2696 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002697 errorMsg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002698 (unsigned long) sec->header.sh_entsize,
2699 (unsigned long) sizeof(ElfW(Sym)));
2700 return NULL;
2701 }
2702
2703 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2704 strtab = f->sections[sec->header.sh_link]->contents;
2705 sym = (ElfW(Sym) *) sec->contents;
2706
2707 /* Allocate space for a table of local symbols. */
2708 j = f->local_symtab_size = sec->header.sh_info;
2709 f->local_symtab = xmalloc(j *=
2710 sizeof(struct obj_symbol *));
2711 memset(f->local_symtab, 0, j);
2712
2713 /* Insert all symbols into the hash table. */
2714 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2715 const char *name;
2716 if (sym->st_name)
2717 name = strtab + sym->st_name;
2718 else
2719 name = f->sections[sym->st_shndx]->name;
2720
2721 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2722 sym->st_value, sym->st_size);
2723 }
2724 }
2725 break;
2726
2727 case SHT_RELM:
2728 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002729 errorMsg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002730 (unsigned long) sec->header.sh_entsize,
2731 (unsigned long) sizeof(ElfW(RelM)));
2732 return NULL;
2733 }
2734 break;
2735 }
2736 }
2737
2738 return f;
2739}
2740
2741static void hide_special_symbols(struct obj_file *f)
2742{
2743 static const char *const specials[] = {
2744 "cleanup_module",
2745 "init_module",
2746 "kernel_version",
2747 NULL
2748 };
2749
2750 struct obj_symbol *sym;
2751 const char *const *p;
2752
2753 for (p = specials; *p; ++p)
2754 if ((sym = obj_find_symbol(f, *p)) != NULL)
2755 sym->info =
2756 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2757}
2758
2759
2760
2761extern int insmod_main( int argc, char **argv)
2762{
2763 int k_crcs;
2764 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002765 int len;
2766 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002767 unsigned long m_size;
2768 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002769 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002770 struct obj_file *f;
2771 char m_name[BUFSIZ + 1] = "\0";
2772 int exit_status = FALSE;
2773 int m_has_modinfo;
2774#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2775 int k_version;
2776 char k_strversion[STRVERSIONLEN];
2777 char m_strversion[STRVERSIONLEN];
2778 int m_version;
2779 int m_crcs;
2780#endif
2781
Erik Andersen02104321999-12-17 18:57:34 +00002782
Erik Andersene49d5ec2000-02-08 19:58:47 +00002783 if (argc <= 1) {
Erik Andersen02104321999-12-17 18:57:34 +00002784 usage(insmod_usage);
Erik Andersen02104321999-12-17 18:57:34 +00002785 }
Erik Andersen02104321999-12-17 18:57:34 +00002786
Erik Andersene49d5ec2000-02-08 19:58:47 +00002787 /* Parse any options */
2788 while (--argc > 0 && **(++argv) == '-') {
2789 while (*(++(*argv))) {
2790 switch (**argv) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002791 case 'f': /* force loading */
2792 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002793 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002794 case 'k': /* module loaded by kerneld, auto-cleanable */
2795 flag_autoclean = 1;
2796 break;
2797 case 'v': /* verbose output */
2798 flag_verbose = 1;
2799 break;
2800 case 'x': /* do not export externs */
2801 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002802 break;
2803 default:
2804 usage(insmod_usage);
2805 }
2806 }
Erik Andersend387d011999-12-21 02:55:11 +00002807 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002808
Eric Andersen9f16d612000-06-12 23:11:16 +00002809 if (argc <= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002810 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002811 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002812 /* Grab the module name */
Eric Andersen9f16d612000-06-12 23:11:16 +00002813 if ((tmp = strrchr(*argv, '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002814 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002815 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002816 tmp = *argv;
Eric Andersen9f16d612000-06-12 23:11:16 +00002817 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002818 len = strlen(tmp);
2819
2820 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2821 len -= 2;
2822 memcpy(m_name, tmp, len);
2823 strcpy(m_fullName, m_name);
2824 strcat(m_fullName, ".o");
2825
2826 /* Get a filedesc for the module */
2827 if ((fp = fopen(*argv, "r")) == NULL) {
2828 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
2829 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002830 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002831 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002832 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002833 || ((fp = fopen(m_filename, "r")) == NULL))
2834 {
Eric Andersen8a24a672000-06-22 18:19:31 +00002835 errorMsg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002836 exit(FALSE);
2837 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002838 } else
2839 fatalError("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002840 } else
2841 memcpy(m_filename, *argv, strlen(*argv));
Erik Andersend387d011999-12-21 02:55:11 +00002842
2843
Erik Andersene49d5ec2000-02-08 19:58:47 +00002844 if ((f = obj_load(fp)) == NULL) {
2845 perror("Could not load the module\n");
2846 exit(FALSE);
Erik Andersend387d011999-12-21 02:55:11 +00002847 }
Erik Andersend387d011999-12-21 02:55:11 +00002848
Eric Andersen9f16d612000-06-12 23:11:16 +00002849 if (get_modinfo_value(f, "kernel_version") == NULL)
2850 m_has_modinfo = 0;
2851 else
2852 m_has_modinfo = 1;
2853
2854#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2855 /* Version correspondence? */
2856
2857 k_version = get_kernel_version(k_strversion);
2858 if (m_has_modinfo) {
2859 m_version = new_get_module_version(f, m_strversion);
2860 } else {
2861 m_version = old_get_module_version(f, m_strversion);
2862 if (m_version == -1) {
Matt Kraaid537a952000-07-14 01:51:25 +00002863 errorMsg("couldn't find the kernel version the module was "
2864 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002865 goto out;
2866 }
2867 }
2868
2869 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2870 if (flag_force_load) {
Matt Kraaid537a952000-07-14 01:51:25 +00002871 errorMsg("Warning: 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 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002876 errorMsg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002877 "\t%s was compiled for kernel version %s\n"
2878 "\twhile this kernel is version %s.\n",
2879 m_filename, m_strversion, k_strversion);
2880 goto out;
2881 }
2882 }
2883 k_crcs = 0;
2884#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2885
2886 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2887
2888 if (k_new_syscalls) {
2889#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
2890 if (!new_get_kernel_symbols())
2891 goto out;
2892 k_crcs = new_is_kernel_checksummed();
2893#else
Matt Kraaid537a952000-07-14 01:51:25 +00002894 errorMsg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002895 goto out;
2896#endif
2897 } else {
2898#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
Eric Andersen8c185f92000-09-22 00:38:07 +00002899 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00002900 goto out;
2901 k_crcs = old_is_kernel_checksummed();
2902#else
Matt Kraaid537a952000-07-14 01:51:25 +00002903 errorMsg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002904 goto out;
2905#endif
2906 }
2907
2908#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2909 if (m_has_modinfo)
2910 m_crcs = new_is_module_checksummed(f);
2911 else
2912 m_crcs = old_is_module_checksummed(f);
2913
2914 if (m_crcs != k_crcs)
2915 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
2916#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2917
Erik Andersene49d5ec2000-02-08 19:58:47 +00002918 /* Let the module know about the kernel symbols. */
2919 add_kernel_symbols(f);
2920
Eric Andersen9f16d612000-06-12 23:11:16 +00002921 /* Allocate common symbols, symbol tables, and string tables. */
2922
2923 if (k_new_syscalls
2924 ? !new_create_this_module(f, m_name)
2925 : !old_create_mod_use_count(f))
2926 {
2927 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002928 }
2929
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 if (!obj_check_undefineds(f)) {
2931 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002932 }
2933 obj_allocate_commons(f);
2934
Eric Andersen9f16d612000-06-12 23:11:16 +00002935 if (optind < argc) {
2936 if (m_has_modinfo
2937 ? !new_process_module_arguments(f, argc - optind, argv + optind)
2938 : !old_process_module_arguments(f, argc - optind, argv + optind))
2939 {
2940 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002941 }
2942 }
2943
Eric Andersen9f16d612000-06-12 23:11:16 +00002944 arch_create_got(f);
2945 hide_special_symbols(f);
2946
2947 if (k_new_syscalls)
2948 new_create_module_ksymtab(f);
2949
Erik Andersene49d5ec2000-02-08 19:58:47 +00002950 /* Find current size of the module */
2951 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00002952
2953
Erik Andersene49d5ec2000-02-08 19:58:47 +00002954 errno = 0;
2955 m_addr = create_module(m_name, m_size);
2956 switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002957 case 0:
2958 break;
2959 case EEXIST:
Matt Kraaid537a952000-07-14 01:51:25 +00002960 errorMsg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002961 goto out;
2962 case ENOMEM:
Matt Kraaid537a952000-07-14 01:51:25 +00002963 errorMsg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002964 m_size);
2965 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00002966 default:
Matt Kraai2be47972000-10-23 17:55:27 +00002967 errorMsg("create_module: %s: %s\n", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002968 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002969 }
Erik Andersend387d011999-12-21 02:55:11 +00002970
Eric Andersen9f16d612000-06-12 23:11:16 +00002971 if (!obj_relocate(f, m_addr)) {
2972 delete_module(m_name);
2973 goto out;
2974 }
Erik Andersend387d011999-12-21 02:55:11 +00002975
Eric Andersen9f16d612000-06-12 23:11:16 +00002976 if (k_new_syscalls
2977 ? !new_init_module(m_name, f, m_size)
2978 : !old_init_module(m_name, f, m_size))
2979 {
2980 delete_module(m_name);
2981 goto out;
2982 }
2983
2984 exit_status = TRUE;
2985
2986out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00002987 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00002988 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00002989}