diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-21 16:09:18 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-21 16:09:18 +0000 |
commit | 8ae319a32228dff15f4b9696deb5883fb242f024 (patch) | |
tree | bd1306d5a4a1f218d8c244ad5000248c5f518b90 /insmod.c | |
parent | 2f6e1f880b630751fa20cb29bafc06aa0f3d0fcb (diff) | |
download | busybox-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.c | 159 |
1 files changed, 152 insertions, 7 deletions
@@ -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 |
125 | static const int MODUTILS_MODULE_H = 1; | 131 | static 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 | |||
262 | struct new_module_info | 279 | struct 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 |
331 | static const int MODUTILS_OBJ_H = 1; | 348 | static 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 | ||
559 | int obj_relocate (struct obj_file *f, ElfW(Addr) base); | 590 | int obj_relocate (struct obj_file *f, ElfW(Addr) base); |
560 | 591 | ||
561 | struct obj_file *obj_load(FILE *f); | 592 | struct obj_file *obj_load(FILE *f, int loadprogbits); |
562 | 593 | ||
563 | int obj_create_image (struct obj_file *f, char *image); | 594 | int 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 | ||
2887 | struct obj_file *obj_load(FILE * fp) | 2980 | struct 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 | |||
3186 | int 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 | |||
3081 | static void hide_special_symbols(struct obj_file *f) | 3213 | static 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; |