diff options
| author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-21 16:09:18 +0000 |
|---|---|---|
| committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-21 16:09:18 +0000 |
| commit | 594efec0019df74bb65354f68d85fa82a35efde7 (patch) | |
| tree | bd1306d5a4a1f218d8c244ad5000248c5f518b90 /modutils/insmod.c | |
| parent | f560dbd0639d9146b593f1bd0a1834d039e670cc (diff) | |
| download | busybox-w32-594efec0019df74bb65354f68d85fa82a35efde7.tar.gz busybox-w32-594efec0019df74bb65354f68d85fa82a35efde7.tar.bz2 busybox-w32-594efec0019df74bb65354f68d85fa82a35efde7.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.
git-svn-id: svn://busybox.net/trunk/busybox@2681 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'modutils/insmod.c')
| -rw-r--r-- | modutils/insmod.c | 159 |
1 files changed, 152 insertions, 7 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index 0644affd1..5e51fcb70 100644 --- a/modutils/insmod.c +++ b/modutils/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 |
| 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; |
