1/* 2 * arch/xtensa/kernel/module.c 3 * 4 * Module support. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 * 10 * Copyright (C) 2001 - 2006 Tensilica Inc. 11 * 12 * Chris Zankel <chris@zankel.net> 13 * 14 */ 15 16#include <linux/module.h> 17#include <linux/moduleloader.h> 18#include <linux/elf.h> 19#include <linux/vmalloc.h> 20#include <linux/fs.h> 21#include <linux/string.h> 22#include <linux/kernel.h> 23#include <linux/cache.h> 24 25#undef DEBUG_RELOCATE 26 27void *module_alloc(unsigned long size) 28{ 29 if (size == 0) 30 return NULL; 31 return vmalloc_exec(size); 32} 33 34void module_free(struct module *mod, void *module_region) 35{ 36 vfree(module_region); 37} 38 39int module_frob_arch_sections(Elf32_Ehdr *hdr, 40 Elf32_Shdr *sechdrs, 41 char *secstrings, 42 struct module *mod) 43{ 44 return 0; 45} 46 47static int 48decode_calln_opcode (unsigned char *location) 49{ 50#ifdef __XTENSA_EB__ 51 return (location[0] & 0xf0) == 0x50; 52#endif 53#ifdef __XTENSA_EL__ 54 return (location[0] & 0xf) == 0x5; 55#endif 56} 57 58static int 59decode_l32r_opcode (unsigned char *location) 60{ 61#ifdef __XTENSA_EB__ 62 return (location[0] & 0xf0) == 0x10; 63#endif 64#ifdef __XTENSA_EL__ 65 return (location[0] & 0xf) == 0x1; 66#endif 67} 68 69int apply_relocate(Elf32_Shdr *sechdrs, 70 const char *strtab, 71 unsigned int symindex, 72 unsigned int relsec, 73 struct module *mod) 74{ 75 printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", 76 mod->name); 77 return -ENOEXEC; 78 79} 80 81int apply_relocate_add(Elf32_Shdr *sechdrs, 82 const char *strtab, 83 unsigned int symindex, 84 unsigned int relsec, 85 struct module *mod) 86{ 87 unsigned int i; 88 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 89 Elf32_Sym *sym; 90 unsigned char *location; 91 uint32_t value; 92 93#ifdef DEBUG_RELOCATE 94 printk("Applying relocate section %u to %u\n", relsec, 95 sechdrs[relsec].sh_info); 96#endif 97 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 98 location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr 99 + rela[i].r_offset; 100 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 101 + ELF32_R_SYM(rela[i].r_info); 102 value = sym->st_value + rela[i].r_addend; 103 104 switch (ELF32_R_TYPE(rela[i].r_info)) { 105 case R_XTENSA_NONE: 106 case R_XTENSA_DIFF8: 107 case R_XTENSA_DIFF16: 108 case R_XTENSA_DIFF32: 109 case R_XTENSA_ASM_EXPAND: 110 break; 111 112 case R_XTENSA_32: 113 case R_XTENSA_PLT: 114 *(uint32_t *)location += value; 115 break; 116 117 case R_XTENSA_SLOT0_OP: 118 if (decode_calln_opcode(location)) { 119 value -= ((unsigned long)location & -4) + 4; 120 if ((value & 3) != 0 || 121 ((value + (1 << 19)) >> 20) != 0) { 122 printk("%s: relocation out of range, " 123 "section %d reloc %d " 124 "sym '%s'\n", 125 mod->name, relsec, i, 126 strtab + sym->st_name); 127 return -ENOEXEC; 128 } 129 value = (signed int)value >> 2; 130#ifdef __XTENSA_EB__ 131 location[0] = ((location[0] & ~0x3) | 132 ((value >> 16) & 0x3)); 133 location[1] = (value >> 8) & 0xff; 134 location[2] = value & 0xff; 135#endif 136#ifdef __XTENSA_EL__ 137 location[0] = ((location[0] & ~0xc0) | 138 ((value << 6) & 0xc0)); 139 location[1] = (value >> 2) & 0xff; 140 location[2] = (value >> 10) & 0xff; 141#endif 142 } else if (decode_l32r_opcode(location)) { 143 value -= (((unsigned long)location + 3) & -4); 144 if ((value & 3) != 0 || 145 (signed int)value >> 18 != -1) { 146 printk("%s: relocation out of range, " 147 "section %d reloc %d " 148 "sym '%s'\n", 149 mod->name, relsec, i, 150 strtab + sym->st_name); 151 return -ENOEXEC; 152 } 153 value = (signed int)value >> 2; 154 155#ifdef __XTENSA_EB__ 156 location[1] = (value >> 8) & 0xff; 157 location[2] = value & 0xff; 158#endif 159#ifdef __XTENSA_EL__ 160 location[1] = value & 0xff; 161 location[2] = (value >> 8) & 0xff; 162#endif 163 } 164 break; 165 166 case R_XTENSA_SLOT1_OP: 167 case R_XTENSA_SLOT2_OP: 168 case R_XTENSA_SLOT3_OP: 169 case R_XTENSA_SLOT4_OP: 170 case R_XTENSA_SLOT5_OP: 171 case R_XTENSA_SLOT6_OP: 172 case R_XTENSA_SLOT7_OP: 173 case R_XTENSA_SLOT8_OP: 174 case R_XTENSA_SLOT9_OP: 175 case R_XTENSA_SLOT10_OP: 176 case R_XTENSA_SLOT11_OP: 177 case R_XTENSA_SLOT12_OP: 178 case R_XTENSA_SLOT13_OP: 179 case R_XTENSA_SLOT14_OP: 180 printk("%s: unexpected FLIX relocation: %u\n", 181 mod->name, 182 ELF32_R_TYPE(rela[i].r_info)); 183 return -ENOEXEC; 184 185 case R_XTENSA_SLOT0_ALT: 186 case R_XTENSA_SLOT1_ALT: 187 case R_XTENSA_SLOT2_ALT: 188 case R_XTENSA_SLOT3_ALT: 189 case R_XTENSA_SLOT4_ALT: 190 case R_XTENSA_SLOT5_ALT: 191 case R_XTENSA_SLOT6_ALT: 192 case R_XTENSA_SLOT7_ALT: 193 case R_XTENSA_SLOT8_ALT: 194 case R_XTENSA_SLOT9_ALT: 195 case R_XTENSA_SLOT10_ALT: 196 case R_XTENSA_SLOT11_ALT: 197 case R_XTENSA_SLOT12_ALT: 198 case R_XTENSA_SLOT13_ALT: 199 case R_XTENSA_SLOT14_ALT: 200 printk("%s: unexpected ALT relocation: %u\n", 201 mod->name, 202 ELF32_R_TYPE(rela[i].r_info)); 203 return -ENOEXEC; 204 205 default: 206 printk("%s: unexpected relocation: %u\n", 207 mod->name, 208 ELF32_R_TYPE(rela[i].r_info)); 209 return -ENOEXEC; 210 } 211 } 212 return 0; 213} 214 215int module_finalize(const Elf_Ehdr *hdr, 216 const Elf_Shdr *sechdrs, 217 struct module *mod) 218{ 219 return 0; 220} 221 222void module_arch_cleanup(struct module *mod) 223{ 224} 225