aboutsummaryrefslogtreecommitdiff
path: root/insmod.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-21 16:09:18 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-21 16:09:18 +0000
commit8ae319a32228dff15f4b9696deb5883fb242f024 (patch)
treebd1306d5a4a1f218d8c244ad5000248c5f518b90 /insmod.c
parent2f6e1f880b630751fa20cb29bafc06aa0f3d0fcb (diff)
downloadbusybox-w32-8ae319a32228dff15f4b9696deb5883fb242f024.tar.gz
busybox-w32-8ae319a32228dff15f4b9696deb5883fb242f024.tar.bz2
busybox-w32-8ae319a32228dff15f4b9696deb5883fb242f024.zip
This patch from Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de> is based on
the work of Jinux Kim on his "babobox" (derived from busybox-0.42), and enables kernel module loading and unloading for uClinux/m68k.
Diffstat (limited to 'insmod.c')
-rw-r--r--insmod.c159
1 files changed, 152 insertions, 7 deletions
diff --git a/insmod.c b/insmod.c
index 0644affd1..5e51fcb70 100644
--- a/insmod.c
+++ b/insmod.c
@@ -69,6 +69,12 @@
69# define old_sys_init_module init_module 69# define old_sys_init_module init_module
70#endif 70#endif
71 71
72#ifdef BB_FEATURE_INSMOD_LOADINKMEM
73#define LOADBITS 0
74#else
75#define LOADBITS 1
76#endif
77
72#if defined(__powerpc__) 78#if defined(__powerpc__)
73#define BB_USE_PLT_ENTRIES 79#define BB_USE_PLT_ENTRIES
74#define BB_PLT_ENTRY_SIZE 16 80#define BB_PLT_ENTRY_SIZE 16
@@ -124,7 +130,7 @@
124#ifndef MODUTILS_MODULE_H 130#ifndef MODUTILS_MODULE_H
125static const int MODUTILS_MODULE_H = 1; 131static const int MODUTILS_MODULE_H = 1;
126 132
127#ident "$Id: insmod.c,v 1.63 2001/05/14 20:03:04 andersen Exp $" 133#ident "$Id: insmod.c,v 1.64 2001/05/21 16:09:18 andersen Exp $"
128 134
129/* This file contains the structures used by the 2.0 and 2.1 kernels. 135/* This file contains the structures used by the 2.0 and 2.1 kernels.
130 We do not use the kernel headers directly because we do not wish 136 We do not use the kernel headers directly because we do not wish
@@ -257,8 +263,19 @@ struct new_module
257 unsigned tgt_long persist_end; 263 unsigned tgt_long persist_end;
258 unsigned tgt_long can_unload; 264 unsigned tgt_long can_unload;
259 unsigned tgt_long runsize; 265 unsigned tgt_long runsize;
266#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
267 const char *kallsyms_start; /* All symbols for kernel debugging */
268 const char *kallsyms_end;
269 const char *archdata_start; /* arch specific data for module */
270 const char *archdata_end;
271 const char *kernel_data; /* Reserved for kernel internal use */
272#endif
260}; 273};
261 274
275#define ARCHDATA_SEC_NAME "__archdata"
276#define KALLSYMS_SEC_NAME "__kallsyms"
277
278
262struct new_module_info 279struct new_module_info
263{ 280{
264 unsigned long addr; 281 unsigned long addr;
@@ -330,7 +347,7 @@ int delete_module(const char *);
330#ifndef MODUTILS_OBJ_H 347#ifndef MODUTILS_OBJ_H
331static const int MODUTILS_OBJ_H = 1; 348static const int MODUTILS_OBJ_H = 1;
332 349
333#ident "$Id: insmod.c,v 1.63 2001/05/14 20:03:04 andersen Exp $" 350#ident "$Id: insmod.c,v 1.64 2001/05/21 16:09:18 andersen Exp $"
334 351
335/* The relocatable object is manipulated using elfin types. */ 352/* The relocatable object is manipulated using elfin types. */
336 353
@@ -355,6 +372,14 @@ static const int MODUTILS_OBJ_H = 1;
355 372
356#define ELFCLASSM ELFCLASS32 373#define ELFCLASSM ELFCLASS32
357 374
375#if (defined(__m68k__))
376#define ELFDATAM ELFDATA2MSB
377#else
378#define ELFDATAM ELFDATA2LSB
379#endif
380
381
382
358#if defined(__sh__) 383#if defined(__sh__)
359 384
360#define MATCH_MACHINE(x) (x == EM_SH) 385#define MATCH_MACHINE(x) (x == EM_SH)
@@ -412,6 +437,12 @@ static const int MODUTILS_OBJ_H = 1;
412#define Elf32_RelM Elf32_Rel 437#define Elf32_RelM Elf32_Rel
413#define ELFDATAM ELFDATA2LSB 438#define ELFDATAM ELFDATA2LSB
414 439
440#elif defined(__m68k__)
441
442#define MATCH_MACHINE(x) (x == EM_68K)
443#define SHT_RELM SHT_RELA
444#define Elf32_RelM Elf32_Rela
445
415#else 446#else
416#error Sorry, but insmod.c does not yet support this architecture... 447#error Sorry, but insmod.c does not yet support this architecture...
417#endif 448#endif
@@ -558,7 +589,7 @@ unsigned long obj_load_size (struct obj_file *f);
558 589
559int obj_relocate (struct obj_file *f, ElfW(Addr) base); 590int obj_relocate (struct obj_file *f, ElfW(Addr) base);
560 591
561struct obj_file *obj_load(FILE *f); 592struct obj_file *obj_load(FILE *f, int loadprogbits);
562 593
563int obj_create_image (struct obj_file *f, char *image); 594int obj_create_image (struct obj_file *f, char *image);
564 595
@@ -784,6 +815,8 @@ arch_apply_relocation(struct obj_file *f,
784 case R_ARM_NONE: 815 case R_ARM_NONE:
785#elif defined(__i386__) 816#elif defined(__i386__)
786 case R_386_NONE: 817 case R_386_NONE:
818#elif defined(__m68k__)
819 case R_68K_NONE:
787#elif defined(__powerpc__) 820#elif defined(__powerpc__)
788 case R_PPC_NONE: 821 case R_PPC_NONE:
789#elif defined(__mips__) 822#elif defined(__mips__)
@@ -797,6 +830,8 @@ arch_apply_relocation(struct obj_file *f,
797 case R_ARM_ABS32: 830 case R_ARM_ABS32:
798#elif defined(__i386__) 831#elif defined(__i386__)
799 case R_386_32: 832 case R_386_32:
833#elif defined(__m68k__)
834 case R_68K_32:
800#elif defined(__powerpc__) 835#elif defined(__powerpc__)
801 case R_PPC_ADDR32: 836 case R_PPC_ADDR32:
802#elif defined(__mips__) 837#elif defined(__mips__)
@@ -804,6 +839,18 @@ arch_apply_relocation(struct obj_file *f,
804#endif 839#endif
805 *loc += v; 840 *loc += v;
806 break; 841 break;
842#if defined(__m68k__)
843 case R_68K_8:
844 if (v > 0xff)
845 ret = obj_reloc_overflow;
846 *(char *)loc = v;
847 break;
848 case R_68K_16:
849 if (v > 0xffff)
850 ret = obj_reloc_overflow;
851 *(short *)loc = v;
852 break;
853#endif /* __m68k__ */
807 854
808#if defined(__powerpc__) 855#if defined(__powerpc__)
809 case R_PPC_ADDR16_HA: 856 case R_PPC_ADDR16_HA:
@@ -909,6 +956,22 @@ arch_apply_relocation(struct obj_file *f,
909 case R_386_PC32: 956 case R_386_PC32:
910 *loc += v - dot; 957 *loc += v - dot;
911 break; 958 break;
959#elif defined(__m68k__)
960 case R_68K_PC8:
961 v -= dot;
962 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
963 ret = obj_reloc_overflow;
964 *(char *)loc = v;
965 break;
966 case R_68K_PC16:
967 v -= dot;
968 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
969 ret = obj_reloc_overflow;
970 *(short *)loc = v;
971 break;
972 case R_68K_PC32:
973 *(int *)loc = v - dot;
974 break;
912#elif defined(__powerpc__) 975#elif defined(__powerpc__)
913 case R_PPC_REL32: 976 case R_PPC_REL32:
914 *loc = v - dot; 977 *loc = v - dot;
@@ -988,6 +1051,11 @@ arch_apply_relocation(struct obj_file *f,
988 case R_386_JMP_SLOT: 1051 case R_386_JMP_SLOT:
989 *loc = v; 1052 *loc = v;
990 break; 1053 break;
1054#elif defined(__m68k__)
1055 case R_68K_GLOB_DAT:
1056 case R_68K_JMP_SLOT:
1057 *loc = v;
1058 break;
991#endif 1059#endif
992 1060
993#if defined(__arm__) 1061#if defined(__arm__)
@@ -999,10 +1067,15 @@ arch_apply_relocation(struct obj_file *f,
999 case R_386_RELATIVE: 1067 case R_386_RELATIVE:
1000 *loc += f->baseaddr; 1068 *loc += f->baseaddr;
1001 break; 1069 break;
1070#elif defined(__m68k__)
1071 case R_68K_RELATIVE:
1072 *(int *)loc += f->baseaddr;
1073 break;
1002#endif 1074#endif
1003 1075
1004#if defined(BB_USE_GOT_ENTRIES) 1076#if defined(BB_USE_GOT_ENTRIES)
1005 1077
1078#if !defined(__68k__)
1006#if defined(__sh__) 1079#if defined(__sh__)
1007 case R_SH_GOTPC: 1080 case R_SH_GOTPC:
1008#elif defined(__arm__) 1081#elif defined(__arm__)
@@ -1013,10 +1086,11 @@ arch_apply_relocation(struct obj_file *f,
1013 assert(got != 0); 1086 assert(got != 0);
1014#if defined(__sh__) 1087#if defined(__sh__)
1015 *loc += got - dot + rel->r_addend;; 1088 *loc += got - dot + rel->r_addend;;
1016#elif defined(__i386__) || defined(__arm__) 1089#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
1017 *loc += got - dot; 1090 *loc += got - dot;
1018#endif 1091#endif
1019 break; 1092 break;
1093#endif // __68k__
1020 1094
1021#if defined(__sh__) 1095#if defined(__sh__)
1022 case R_SH_GOT32: 1096 case R_SH_GOT32:
@@ -1024,6 +1098,8 @@ arch_apply_relocation(struct obj_file *f,
1024 case R_ARM_GOT32: 1098 case R_ARM_GOT32:
1025#elif defined(__i386__) 1099#elif defined(__i386__)
1026 case R_386_GOT32: 1100 case R_386_GOT32:
1101#elif defined(__m68k__)
1102 case R_68K_GOT32:
1027#endif 1103#endif
1028 assert(isym != NULL); 1104 assert(isym != NULL);
1029 /* needs an entry in the .got: set it, once */ 1105 /* needs an entry in the .got: set it, once */
@@ -1034,22 +1110,26 @@ arch_apply_relocation(struct obj_file *f,
1034 /* make the reloc with_respect_to_.got */ 1110 /* make the reloc with_respect_to_.got */
1035#if defined(__sh__) 1111#if defined(__sh__)
1036 *loc += isym->gotent.offset + rel->r_addend; 1112 *loc += isym->gotent.offset + rel->r_addend;
1037#elif defined(__i386__) || defined(__arm__) 1113#elif defined(__i386__) || defined(__arm__) || defined(__m68k__)
1038 *loc += isym->gotent.offset; 1114 *loc += isym->gotent.offset;
1039#endif 1115#endif
1040 break; 1116 break;
1041 1117
1042 /* address relative to the got */ 1118 /* address relative to the got */
1119#if !defined(__m68k__)
1043#if defined(__sh__) 1120#if defined(__sh__)
1044 case R_SH_GOTOFF: 1121 case R_SH_GOTOFF:
1045#elif defined(__arm__) 1122#elif defined(__arm__)
1046 case R_ARM_GOTOFF: 1123 case R_ARM_GOTOFF:
1047#elif defined(__i386__) 1124#elif defined(__i386__)
1048 case R_386_GOTOFF: 1125 case R_386_GOTOFF:
1126#elif defined(__m68k__)
1127 case R_68K_GOTOFF:
1049#endif 1128#endif
1050 assert(got != 0); 1129 assert(got != 0);
1051 *loc += v - got; 1130 *loc += v - got;
1052 break; 1131 break;
1132#endif // __m68k__
1053 1133
1054#endif /* BB_USE_GOT_ENTRIES */ 1134#endif /* BB_USE_GOT_ENTRIES */
1055 1135
@@ -1105,6 +1185,9 @@ int arch_create_got(struct obj_file *f)
1105#elif defined(__i386__) 1185#elif defined(__i386__)
1106 case R_386_GOT32: 1186 case R_386_GOT32:
1107 break; 1187 break;
1188#elif defined(__m68k__)
1189 case R_68K_GOT32:
1190 break;
1108#endif 1191#endif
1109 1192
1110#if defined(__powerpc__) 1193#if defined(__powerpc__)
@@ -2504,6 +2587,16 @@ new_init_module(const char *m_name, struct obj_file *f,
2504 module->runsize > sec->header.sh_addr - m_addr) 2587 module->runsize > sec->header.sh_addr - m_addr)
2505 module->runsize = sec->header.sh_addr - m_addr; 2588 module->runsize = sec->header.sh_addr - m_addr;
2506 } 2589 }
2590 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2591 if (sec && sec->header.sh_size) {
2592 module->archdata_start = (void*)sec->header.sh_addr;
2593 module->archdata_end = module->archdata_start + sec->header.sh_size;
2594 }
2595 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2596 if (sec && sec->header.sh_size) {
2597 module->kallsyms_start = (void*)sec->header.sh_addr;
2598 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2599 }
2507 2600
2508 if (!arch_init_module(f, module)) 2601 if (!arch_init_module(f, module))
2509 return 0; 2602 return 0;
@@ -2884,7 +2977,7 @@ int obj_create_image(struct obj_file *f, char *image)
2884 2977
2885/*======================================================================*/ 2978/*======================================================================*/
2886 2979
2887struct obj_file *obj_load(FILE * fp) 2980struct obj_file *obj_load(FILE * fp, int loadprogbits)
2888{ 2981{
2889 struct obj_file *f; 2982 struct obj_file *f;
2890 ElfW(Shdr) * section_headers; 2983 ElfW(Shdr) * section_headers;
@@ -2963,6 +3056,12 @@ struct obj_file *obj_load(FILE * fp)
2963 break; 3056 break;
2964 3057
2965 case SHT_PROGBITS: 3058 case SHT_PROGBITS:
3059#if LOADBITS
3060 if (!loadprogbits) {
3061 sec->contents = NULL;
3062 break;
3063 }
3064#endif
2966 case SHT_SYMTAB: 3065 case SHT_SYMTAB:
2967 case SHT_STRTAB: 3066 case SHT_STRTAB:
2968 case SHT_RELM: 3067 case SHT_RELM:
@@ -3078,6 +3177,39 @@ struct obj_file *obj_load(FILE * fp)
3078 return f; 3177 return f;
3079} 3178}
3080 3179
3180#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3181/*
3182 * load the unloaded sections directly into the memory allocated by
3183 * kernel for the module
3184 */
3185
3186int obj_load_progbits(FILE * fp, struct obj_file* f)
3187{
3188 char* imagebase = (char*) f->imagebase;
3189 ElfW(Addr) base = f->baseaddr;
3190 struct obj_section* sec;
3191
3192 for (sec = f->load_order; sec; sec = sec->load_next) {
3193
3194 /* section already loaded? */
3195 if (sec->contents != NULL)
3196 continue;
3197
3198 if (sec->header.sh_size == 0)
3199 continue;
3200
3201 sec->contents = imagebase + (sec->header.sh_addr - base);
3202 fseek(fp, sec->header.sh_offset, SEEK_SET);
3203 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3204 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3205 return 0;
3206 }
3207
3208 }
3209 return 1;
3210}
3211#endif
3212
3081static void hide_special_symbols(struct obj_file *f) 3213static void hide_special_symbols(struct obj_file *f)
3082{ 3214{
3083 static const char *const specials[] = { 3215 static const char *const specials[] = {
@@ -3219,7 +3351,7 @@ extern int insmod_main( int argc, char **argv)
3219 3351
3220 printf("Using %s\n", m_filename); 3352 printf("Using %s\n", m_filename);
3221 3353
3222 if ((f = obj_load(fp)) == NULL) 3354 if ((f = obj_load(fp, LOADBITS)) == NULL)
3223 perror_msg_and_die("Could not load the module"); 3355 perror_msg_and_die("Could not load the module");
3224 3356
3225 if (get_modinfo_value(f, "kernel_version") == NULL) 3357 if (get_modinfo_value(f, "kernel_version") == NULL)
@@ -3344,6 +3476,19 @@ extern int insmod_main( int argc, char **argv)
3344 goto out; 3476 goto out;
3345 } 3477 }
3346 3478
3479#if !LOADBITS
3480 /*
3481 * the PROGBITS section was not loaded by the obj_load
3482 * now we can load them directly into the kernel memory
3483 */
3484 // f->imagebase = (char*) m_addr;
3485 f->imagebase = (ElfW(Addr)) m_addr;
3486 if (!obj_load_progbits(fp, f)) {
3487 delete_module(m_name);
3488 goto out;
3489 }
3490#endif
3491
3347 if (!obj_relocate(f, m_addr)) { 3492 if (!obj_relocate(f, m_addr)) {
3348 delete_module(m_name); 3493 delete_module(m_name);
3349 goto out; 3494 goto out;