1 #include <linux/moduleloader.h> 2 #include <linux/elf.h> 3 #include <linux/vmalloc.h> 4 #include <linux/fs.h> 5 #include <linux/string.h> 6 #include <linux/kernel.h> 7 8 #if 0 9 #define DEBUGP printk 10 #else 11 #define DEBUGP(fmt...) 12 #endif 13 14 void *module_alloc(unsigned long size) 15 { 16 if (size == 0) 17 return NULL; 18 return vmalloc(size); 19 } 20 21 22 /* Free memory returned from module_alloc */ 23 void module_free(struct module *mod, void *module_region) 24 { 25 vfree(module_region); 26 /* FIXME: If module_region == mod->init_region, trim exception 27 table entries. */ 28 } 29 30 /* We don't need anything special. */ 31 int module_frob_arch_sections(Elf_Ehdr *hdr, 32 Elf_Shdr *sechdrs, 33 char *secstrings, 34 struct module *mod) 35 { 36 return 0; 37 } 38 39 int apply_relocate(Elf32_Shdr *sechdrs, 40 const char *strtab, 41 unsigned int symindex, 42 unsigned int relsec, 43 struct module *me) 44 { 45 unsigned int i; 46 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; 47 Elf32_Sym *sym; 48 uint32_t *location; 49 50 DEBUGP("Applying relocate section %u to %u\n", relsec, 51 sechdrs[relsec].sh_info); 52 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 53 /* This is where to make the change */ 54 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 55 + rel[i].r_offset; 56 /* This is the symbol it is referring to. Note that all 57 undefined symbols have been resolved. */ 58 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 59 + ELF32_R_SYM(rel[i].r_info); 60 61 switch (ELF32_R_TYPE(rel[i].r_info)) { 62 case R_68K_32: 63 /* We add the value into the location given */ 64 *location += sym->st_value; 65 break; 66 case R_68K_PC32: 67 /* Add the value, subtract its postition */ 68 *location += sym->st_value - (uint32_t)location; 69 break; 70 default: 71 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 72 me->name, ELF32_R_TYPE(rel[i].r_info)); 73 return -ENOEXEC; 74 } 75 } 76 return 0; 77 } 78 79 int apply_relocate_add(Elf32_Shdr *sechdrs, 80 const char *strtab, 81 unsigned int symindex, 82 unsigned int relsec, 83 struct module *me) 84 { 85 unsigned int i; 86 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 87 Elf32_Sym *sym; 88 uint32_t *location; 89 90 DEBUGP("Applying relocate_add section %u to %u\n", relsec, 91 sechdrs[relsec].sh_info); 92 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 93 /* This is where to make the change */ 94 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 95 + rel[i].r_offset; 96 /* This is the symbol it is referring to. Note that all 97 undefined symbols have been resolved. */ 98 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 99 + ELF32_R_SYM(rel[i].r_info); 100 101 switch (ELF32_R_TYPE(rel[i].r_info)) { 102 case R_68K_32: 103 /* We add the value into the location given */ 104 *location = rel[i].r_addend + sym->st_value; 105 break; 106 case R_68K_PC32: 107 /* Add the value, subtract its postition */ 108 *location = rel[i].r_addend + sym->st_value - (uint32_t)location; 109 break; 110 default: 111 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 112 me->name, ELF32_R_TYPE(rel[i].r_info)); 113 return -ENOEXEC; 114 } 115 } 116 return 0; 117 } 118 119 int module_finalize(const Elf_Ehdr *hdr, 120 const Elf_Shdr *sechdrs, 121 struct module *me) 122 { 123 return 0; 124 } 125 126 void module_arch_cleanup(struct module *mod) 127 { 128 } 129