1a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer/* 2a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * This file is subject to the terms and conditions of the GNU General Public 3a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * License. See the file COPYING in the main directory of this archive 4a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * for more details. 5a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer */ 6a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 7a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/moduleloader.h> 8a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/elf.h> 9a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/vmalloc.h> 10a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/fs.h> 11a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/string.h> 12a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/kernel.h> 13a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 14a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#if 0 15a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#define DEBUGP printk 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 17a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#define DEBUGP(fmt...) 18a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#endif 19a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 20a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#ifdef CONFIG_MODULES 21a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 22a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint apply_relocate(Elf32_Shdr *sechdrs, 23a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer const char *strtab, 24a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int symindex, 25a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int relsec, 26a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer struct module *me) 27a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{ 28a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int i; 29a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; 30a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer Elf32_Sym *sym; 31a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer uint32_t *location; 32a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 33a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer DEBUGP("Applying relocate section %u to %u\n", relsec, 34a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer sechdrs[relsec].sh_info); 35a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 36a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* This is where to make the change */ 37a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 38a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer + rel[i].r_offset; 39a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* This is the symbol it is referring to. Note that all 40a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer undefined symbols have been resolved. */ 41a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 42a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer + ELF32_R_SYM(rel[i].r_info); 43a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 44a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer switch (ELF32_R_TYPE(rel[i].r_info)) { 45a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case R_68K_32: 46a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* We add the value into the location given */ 47a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *location += sym->st_value; 48a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 49a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case R_68K_PC32: 50a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* Add the value, subtract its postition */ 51a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *location += sym->st_value - (uint32_t)location; 52a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 53a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer default: 54a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer printk(KERN_ERR "module %s: Unknown relocation: %u\n", 55a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer me->name, ELF32_R_TYPE(rel[i].r_info)); 56a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer return -ENOEXEC; 57a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 58a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 59a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer return 0; 60a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer} 61a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 62a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint apply_relocate_add(Elf32_Shdr *sechdrs, 63a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer const char *strtab, 64a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int symindex, 65a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int relsec, 66a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer struct module *me) 67a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{ 68a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer unsigned int i; 69a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 70a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer Elf32_Sym *sym; 71a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer uint32_t *location; 72a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 73a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer DEBUGP("Applying relocate_add section %u to %u\n", relsec, 74a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer sechdrs[relsec].sh_info); 75a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 76a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* This is where to make the change */ 77a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 78a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer + rel[i].r_offset; 79a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* This is the symbol it is referring to. Note that all 80a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer undefined symbols have been resolved. */ 81a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 82a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer + ELF32_R_SYM(rel[i].r_info); 83a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 84a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer switch (ELF32_R_TYPE(rel[i].r_info)) { 85a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case R_68K_32: 86a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* We add the value into the location given */ 87a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *location = rel[i].r_addend + sym->st_value; 88a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 89a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case R_68K_PC32: 90a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer /* Add the value, subtract its postition */ 91a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *location = rel[i].r_addend + sym->st_value - (uint32_t)location; 92a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 93a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer default: 94a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer printk(KERN_ERR "module %s: Unknown relocation: %u\n", 95a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer me->name, ELF32_R_TYPE(rel[i].r_info)); 96a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer return -ENOEXEC; 97a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 98a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 99a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer return 0; 100a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer} 101a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 102a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint module_finalize(const Elf_Ehdr *hdr, 103a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer const Elf_Shdr *sechdrs, 104a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer struct module *mod) 105a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{ 106a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); 107a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer return 0; 108a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer} 109a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 110a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#endif /* CONFIG_MODULES */ 111a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 112a66af29876b086d8279b48515b83ced66803fb15Greg Ungerervoid module_fixup(struct module *mod, struct m68k_fixup_info *start, 113a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer struct m68k_fixup_info *end) 114a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{ 115a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#ifdef CONFIG_MMU 116a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer struct m68k_fixup_info *fixup; 117a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer 118a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer for (fixup = start; fixup < end; fixup++) { 119a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer switch (fixup->type) { 120a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case m68k_fixup_memoffset: 121a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *(u32 *)fixup->addr = m68k_memoffset; 122a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 123a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer case m68k_fixup_vnode_shift: 124a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer *(u16 *)fixup->addr += m68k_virt_to_node_shift; 125a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer break; 126a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 127a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 129a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer} 130