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