📄 insmod.c
字号:
/* vi: set sw=4 ts=4: *//* * Mini insmod implementation for busybox * * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k, * MIPS, and v850e. * * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen * Copyright (C) 1999,2000,2001,2002 by Erik Andersen <andersee@debian.org> * and Ron Alder <alder@lineo.com> * * Miles Bader <miles@gnu.org> added NEC V850E support. * * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 * and (theoretically) SH3. I have only tested SH4 in little endian mode. * * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only * very minor changes required to also work with StrongArm and presumably * all ARM based systems. * * Magnus Damm <damm@opensource.se> 22-May-2002. * The plt and got code are now using the same structs. * Added generic linked list code to fully support PowerPC. * Replaced the mess in arch_apply_relocation() with architecture blocks. * The arch_create_got() function got cleaned up with architecture blocks. * These blocks should be easy maintain and sync with obj_xxx.c in modutils. * * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001. * PowerPC specific code stolen from modutils-2.3.16, * written by Paul Mackerras, Copyright 1996, 1997 Linux International. * I've only tested the code on mpc8xx platforms in big-endian mode. * Did some cleanup and added CONFIG_USE_xxx_ENTRIES... * * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001. * based on modutils-2.4.2 * MIPS specific support for Elf loading and relocation. * Copyright 1996, 1997 Linux International. * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu> * * Based almost entirely on the Linux modutils-2.3.11 implementation. * Copyright 1996, 1997 Linux International. * New implementation contributed by Richard Henderson <rth@tamu.edu> * Based on original work by Bjorn Ekwall <bj0rn@blox.se> * Restructured (and partly rewritten) by: * Bj鰎n Ekwall <bj0rn@blox.se> February 1999 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <stdlib.h>#include <stdio.h>#include <stddef.h>#include <errno.h>#include <unistd.h>#include <dirent.h>#include <ctype.h>#include <assert.h>#include <string.h>#include <getopt.h>#include <sys/utsname.h>#include "busybox.h"#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE# define new_sys_init_module init_module#else# define old_sys_init_module init_module#endif#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM#define LOADBITS 0 #else#define LOADBITS 1#endif#if defined(__arm__)#define CONFIG_USE_PLT_ENTRIES#define CONFIG_PLT_ENTRY_SIZE 8#define CONFIG_USE_GOT_ENTRIES#define CONFIG_GOT_ENTRY_SIZE 8#define CONFIG_USE_SINGLE#define MATCH_MACHINE(x) (x == EM_ARM)#define SHT_RELM SHT_REL#define Elf32_RelM Elf32_Rel#define ELFCLASSM ELFCLASS32#endif#if defined(__i386__)#define CONFIG_USE_GOT_ENTRIES#define CONFIG_GOT_ENTRY_SIZE 4#define CONFIG_USE_SINGLE#ifndef EM_486#define MATCH_MACHINE(x) (x == EM_386)#else#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)#endif#define SHT_RELM SHT_REL#define Elf32_RelM Elf32_Rel#define ELFCLASSM ELFCLASS32#endif#if defined(__mc68000__) #define CONFIG_USE_GOT_ENTRIES#define CONFIG_GOT_ENTRY_SIZE 4#define CONFIG_USE_SINGLE#define MATCH_MACHINE(x) (x == EM_68K)#define SHT_RELM SHT_RELA#define Elf32_RelM Elf32_Rela#endif#if defined(__mips__)/* Account for ELF spec changes. */#ifndef EM_MIPS_RS3_LE#ifdef EM_MIPS_RS4_BE#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE#else#define EM_MIPS_RS3_LE 10#endif#endif /* !EM_MIPS_RS3_LE */#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)#define SHT_RELM SHT_REL#define Elf32_RelM Elf32_Rel#define ELFCLASSM ELFCLASS32#define ARCHDATAM "__dbe_table"#endif#if defined(__powerpc__)#define CONFIG_USE_PLT_ENTRIES#define CONFIG_PLT_ENTRY_SIZE 16#define CONFIG_USE_PLT_LIST#define CONFIG_LIST_ARCHTYPE ElfW(Addr) #define CONFIG_USE_LIST#define MATCH_MACHINE(x) (x == EM_PPC)#define SHT_RELM SHT_RELA#define Elf32_RelM Elf32_Rela#define ELFCLASSM ELFCLASS32#define ARCHDATAM "__ftr_fixup"#endif#if defined(__sh__)#define CONFIG_USE_GOT_ENTRIES#define CONFIG_GOT_ENTRY_SIZE 4#define CONFIG_USE_SINGLE#define MATCH_MACHINE(x) (x == EM_SH)#define SHT_RELM SHT_RELA#define Elf32_RelM Elf32_Rela#define ELFCLASSM ELFCLASS32/* the SH changes have only been tested on the SH4 in =little endian= mode *//* I'm not sure about big endian, so let's warn: */#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)#error insmod.c may require changes for use on big endian SH4/SH3#endif/* it may or may not work on the SH1/SH2... So let's error on those also */#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))#error insmod.c may require changes for non-SH3/SH4 use#endif#endif#if defined (__v850e__)#define CONFIG_USE_PLT_ENTRIES#define CONFIG_PLT_ENTRY_SIZE 8#define CONFIG_USE_SINGLE#ifndef EM_CYGNUS_V850 /* grumble */#define EM_CYGNUS_V850 0x9080#endif#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)#define SHT_RELM SHT_RELA#define Elf32_RelM Elf32_Rela#define ELFCLASSM ELFCLASS32#define SYMBOL_PREFIX "_"#endif#ifndef SHT_RELM#error Sorry, but insmod.c does not yet support this architecture...#endif//----------------------------------------------------------------------------//--------modutils module.h, lines 45-242//----------------------------------------------------------------------------/* Definitions for the Linux module syscall interface. Copyright 1996, 1997 Linux International. Contributed by Richard Henderson <rth@tamu.edu> This file is part of the Linux modutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifndef MODUTILS_MODULE_Hstatic const int MODUTILS_MODULE_H = 1;#ident "$Id: insmod.c,v 1.87 2002/07/02 19:14:23 andersen Exp $"/* This file contains the structures used by the 2.0 and 2.1 kernels. We do not use the kernel headers directly because we do not wish to be dependant on a particular kernel version to compile insmod. *//*======================================================================*//* The structures used by Linux 2.0. *//* The symbol format used by get_kernel_syms(2). */struct old_kernel_sym{ unsigned long value; char name[60];};struct old_module_ref{ unsigned long module; /* kernel addresses */ unsigned long next;};struct old_module_symbol{ unsigned long addr; unsigned long name;};struct old_symbol_table{ int size; /* total, including string table!!! */ int n_symbols; int n_refs; struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */ struct old_module_ref ref[0]; /* actual size defined by n_refs */};struct old_mod_routines{ unsigned long init; unsigned long cleanup;};struct old_module{ unsigned long next; unsigned long ref; /* the list of modules that refer to me */ unsigned long symtab; unsigned long name; int size; /* size of module in pages */ unsigned long addr; /* address of module */ int state; unsigned long cleanup; /* cleanup routine */};/* Sent to init_module(2) or'ed into the code size parameter. */static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */int get_kernel_syms(struct old_kernel_sym *);int old_sys_init_module(const char *name, char *code, unsigned codesize, struct old_mod_routines *, struct old_symbol_table *);/*======================================================================*//* For sizeof() which are related to the module platform and not to the environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */#define tgt_sizeof_char sizeof(char)#define tgt_sizeof_short sizeof(short)#define tgt_sizeof_int sizeof(int)#define tgt_sizeof_long sizeof(long)#define tgt_sizeof_char_p sizeof(char *)#define tgt_sizeof_void_p sizeof(void *)#define tgt_long long#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)#undef tgt_sizeof_long#undef tgt_sizeof_char_p#undef tgt_sizeof_void_p#undef tgt_longstatic const int tgt_sizeof_long = 8;static const int tgt_sizeof_char_p = 8;static const int tgt_sizeof_void_p = 8;#define tgt_long long long#endif/*======================================================================*//* The structures used in Linux 2.1. *//* Note: new_module_symbol does not use tgt_long intentionally */struct new_module_symbol{ unsigned long value; unsigned long name;};struct new_module_persist;struct new_module_ref{ unsigned tgt_long dep; /* kernel addresses */ unsigned tgt_long ref; unsigned tgt_long next_ref;};struct new_module{ unsigned tgt_long size_of_struct; /* == sizeof(module) */ unsigned tgt_long next; unsigned tgt_long name; unsigned tgt_long size; tgt_long usecount; unsigned tgt_long flags; /* AUTOCLEAN et al */ unsigned nsyms; unsigned ndeps; unsigned tgt_long syms; unsigned tgt_long deps; unsigned tgt_long refs; unsigned tgt_long init; unsigned tgt_long cleanup; unsigned tgt_long ex_table_start; unsigned tgt_long ex_table_end;#ifdef __alpha__ unsigned tgt_long gp;#endif /* Everything after here is extension. */ unsigned tgt_long persist_start; unsigned tgt_long persist_end; unsigned tgt_long can_unload; unsigned tgt_long runsize;#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE const char *kallsyms_start; /* All symbols for kernel debugging */ const char *kallsyms_end; const char *archdata_start; /* arch specific data for module */ const char *archdata_end; const char *kernel_data; /* Reserved for kernel internal use */#endif};#ifdef ARCHDATAM#define ARCHDATA_SEC_NAME ARCHDATAM#else#define ARCHDATA_SEC_NAME "__archdata"#endif#define KALLSYMS_SEC_NAME "__kallsyms"struct new_module_info{ unsigned long addr; unsigned long size; unsigned long flags; long usecount;};/* Bits of module.flags. */static const int NEW_MOD_RUNNING = 1;static const int NEW_MOD_DELETED = 2;static const int NEW_MOD_AUTOCLEAN = 4;static const int NEW_MOD_VISITED = 8;static const int NEW_MOD_USED_ONCE = 16;int new_sys_init_module(const char *name, const struct new_module *);int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);/* Values for query_module's which. */static const int QM_MODULES = 1;static const int QM_DEPS = 2;static const int QM_REFS = 3;static const int QM_SYMBOLS = 4;static const int QM_INFO = 5;/*======================================================================*//* The system calls unchanged between 2.0 and 2.1. */unsigned long create_module(const char *, size_t);int delete_module(const char *);#endif /* module.h *///----------------------------------------------------------------------------//--------end of modutils module.h//----------------------------------------------------------------------------//----------------------------------------------------------------------------//--------modutils obj.h, lines 253-462//----------------------------------------------------------------------------/* Elf object file loading and relocation routines. Copyright 1996, 1997 Linux International. Contributed by Richard Henderson <rth@tamu.edu> This file is part of the Linux modutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifndef MODUTILS_OBJ_Hstatic const int MODUTILS_OBJ_H = 1;#ident "$Id: insmod.c,v 1.87 2002/07/02 19:14:23 andersen Exp $"/* The relocatable object is manipulated using elfin types. */#include <stdio.h>#include <elf.h>#include <endian.h>#if __BYTE_ORDER == __LITTLE_ENDIAN#define ELFDATAM ELFDATA2LSB#elif __BYTE_ORDER == __BIG_ENDIAN#define ELFDATAM ELFDATA2MSB#endif#ifndef ElfW# if ELFCLASSM == ELFCLASS32# define ElfW(x) Elf32_ ## x# define ELFW(x) ELF32_ ## x# else# define ElfW(x) Elf64_ ## x# define ELFW(x) ELF64_ ## x# endif#endif/* For some reason this is missing from libc5. */#ifndef ELF32_ST_INFO# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))#endif#ifndef ELF64_ST_INFO# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))#endifstruct obj_string_patch;struct obj_symbol_patch;struct obj_section{ ElfW(Shdr) header; const char *name; char *contents; struct obj_section *load_next; int idx;};struct obj_symbol{ struct obj_symbol *next; /* hash table link */ const char *name; unsigned long value; unsigned long size; int secidx; /* the defining section index/module */ int info; int ksymidx; /* for export to the kernel symtab */ int referenced; /* actually used in the link */};/* Hardcode the hash table size. We shouldn't be needing so many symbols that we begin to degrade performance, and we get a big win by giving the compiler a constant divisor. */#define HASH_BUCKETS 521struct obj_file{ ElfW(Ehdr) header; ElfW(Addr) baseaddr; struct obj_section **sections; struct obj_section *load_order; struct obj_section **load_order_search_start; struct obj_string_patch *string_patches; struct obj_symbol_patch *symbol_patches; int (*symbol_cmp)(const char *, const char *); unsigned long (*symbol_hash)(const char *); unsigned long local_symtab_size; struct obj_symbol **local_symtab; struct obj_symbol *symtab[HASH_BUCKETS];};enum obj_reloc{ obj_reloc_ok, obj_reloc_overflow, obj_reloc_dangerous, obj_reloc_unhandled};struct obj_string_patch{ struct obj_string_patch *next; int reloc_secidx; ElfW(Addr) reloc_offset; ElfW(Addr) string_offset;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -