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 27 void *module_alloc(unsigned long size) 28 { 29 if (size == 0) 30 return NULL; 31 return vmalloc_exec(size); 32 } 33 34 void module_free(struct module *mod, void *module_region) 35 { 36 vfree(module_region); 37 /* FIXME: If module_region == mod->init_region, trim exception 38 table entries. */ 39 } 40 41 int module_frob_arch_sections(Elf32_Ehdr *hdr, 42 Elf32_Shdr *sechdrs, 43 char *secstrings, 44 struct module *mod) 45 { 46 return 0; 47 } 48 49 static int 50 decode_calln_opcode (unsigned char *location) 51 { 52 #ifdef __XTENSA_EB__ 53 return (location[0] & 0xf0) == 0x50; 54 #endif 55 #ifdef __XTENSA_EL__ 56 return (location[0] & 0xf) == 0x5; 57 #endif 58 } 59 60 static int 61 decode_l32r_opcode (unsigned char *location) 62 { 63 #ifdef __XTENSA_EB__ 64 return (location[0] & 0xf0) == 0x10; 65 #endif 66 #ifdef __XTENSA_EL__ 67 return (location[0] & 0xf) == 0x1; 68 #endif 69 } 70 71 int apply_relocate(Elf32_Shdr *sechdrs, 72 const char *strtab, 73 unsigned int symindex, 74 unsigned int relsec, 75 struct module *mod) 76 { 77 printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", 78 mod->name); 79 return -ENOEXEC; 80 81 } 82 83 int apply_relocate_add(Elf32_Shdr *sechdrs, 84 const char *strtab, 85 unsigned int symindex, 86 unsigned int relsec, 87 struct module *mod) 88 { 89 unsigned int i; 90 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 91 Elf32_Sym *sym; 92 unsigned char *location; 93 uint32_t value; 94 95 #ifdef DEBUG_RELOCATE 96 printk("Applying relocate section %u to %u\n", relsec, 97 sechdrs[relsec].sh_info); 98 #endif 99 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 100 location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr 101 + rela[i].r_offset; 102 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 103 + ELF32_R_SYM(rela[i].r_info); 104 value = sym->st_value + rela[i].r_addend; 105 106 switch (ELF32_R_TYPE(rela[i].r_info)) { 107 case R_XTENSA_NONE: 108 case R_XTENSA_DIFF8: 109 case R_XTENSA_DIFF16: 110 case R_XTENSA_DIFF32: 111 case R_XTENSA_ASM_EXPAND: 112 break; 113 114 case R_XTENSA_32: 115 case R_XTENSA_PLT: 116 *(uint32_t *)location += value; 117 break; 118 119 case R_XTENSA_SLOT0_OP: 120 if (decode_calln_opcode(location)) { 121 value -= ((unsigned long)location & -4) + 4; 122 if ((value & 3) != 0 || 123 ((value + (1 << 19)) >> 20) != 0) { 124 printk("%s: relocation out of range, " 125 "section %d reloc %d " 126 "sym '%s'\n", 127 mod->name, relsec, i, 128 strtab + sym->st_name); 129 return -ENOEXEC; 130 } 131 value = (signed int)value >> 2; 132 #ifdef __XTENSA_EB__ 133 location[0] = ((location[0] & ~0x3) | 134 ((value >> 16) & 0x3)); 135 location[1] = (value >> 8) & 0xff; 136 location[2] = value & 0xff; 137 #endif 138 #ifdef __XTENSA_EL__ 139 location[0] = ((location[0] & ~0xc0) | 140 ((value << 6) & 0xc0)); 141 location[1] = (value >> 2) & 0xff; 142 location[2] = (value >> 10) & 0xff; 143 #endif 144 } else if (decode_l32r_opcode(location)) { 145 value -= (((unsigned long)location + 3) & -4); 146 if ((value & 3) != 0 || 147 (signed int)value >> 18 != -1) { 148 printk("%s: relocation out of range, " 149 "section %d reloc %d " 150 "sym '%s'\n", 151 mod->name, relsec, i, 152 strtab + sym->st_name); 153 return -ENOEXEC; 154 } 155 value = (signed int)value >> 2; 156 157 #ifdef __XTENSA_EB__ 158 location[1] = (value >> 8) & 0xff; 159 location[2] = value & 0xff; 160 #endif 161 #ifdef __XTENSA_EL__ 162 location[1] = value & 0xff; 163 location[2] = (value >> 8) & 0xff; 164 #endif 165 } 166 /* FIXME: Ignore any other opcodes. The Xtensa 167 assembler currently assumes that the linker will 168 always do relaxation and so all PC-relative 169 operands need relocations. (The assembler also 170 writes out the tentative PC-relative values, 171 assuming no link-time relaxation, so it is usually 172 safe to ignore the relocations.) If the 173 assembler's "--no-link-relax" flag can be made to 174 work, and if all kernel modules can be assembled 175 with that flag, then unexpected relocations could 176 be detected here. */ 177 break; 178 179 case R_XTENSA_SLOT1_OP: 180 case R_XTENSA_SLOT2_OP: 181 case R_XTENSA_SLOT3_OP: 182 case R_XTENSA_SLOT4_OP: 183 case R_XTENSA_SLOT5_OP: 184 case R_XTENSA_SLOT6_OP: 185 case R_XTENSA_SLOT7_OP: 186 case R_XTENSA_SLOT8_OP: 187 case R_XTENSA_SLOT9_OP: 188 case R_XTENSA_SLOT10_OP: 189 case R_XTENSA_SLOT11_OP: 190 case R_XTENSA_SLOT12_OP: 191 case R_XTENSA_SLOT13_OP: 192 case R_XTENSA_SLOT14_OP: 193 printk("%s: unexpected FLIX relocation: %u\n", 194 mod->name, 195 ELF32_R_TYPE(rela[i].r_info)); 196 return -ENOEXEC; 197 198 case R_XTENSA_SLOT0_ALT: 199 case R_XTENSA_SLOT1_ALT: 200 case R_XTENSA_SLOT2_ALT: 201 case R_XTENSA_SLOT3_ALT: 202 case R_XTENSA_SLOT4_ALT: 203 case R_XTENSA_SLOT5_ALT: 204 case R_XTENSA_SLOT6_ALT: 205 case R_XTENSA_SLOT7_ALT: 206 case R_XTENSA_SLOT8_ALT: 207 case R_XTENSA_SLOT9_ALT: 208 case R_XTENSA_SLOT10_ALT: 209 case R_XTENSA_SLOT11_ALT: 210 case R_XTENSA_SLOT12_ALT: 211 case R_XTENSA_SLOT13_ALT: 212 case R_XTENSA_SLOT14_ALT: 213 printk("%s: unexpected ALT relocation: %u\n", 214 mod->name, 215 ELF32_R_TYPE(rela[i].r_info)); 216 return -ENOEXEC; 217 218 default: 219 printk("%s: unexpected relocation: %u\n", 220 mod->name, 221 ELF32_R_TYPE(rela[i].r_info)); 222 return -ENOEXEC; 223 } 224 } 225 return 0; 226 } 227 228 int module_finalize(const Elf_Ehdr *hdr, 229 const Elf_Shdr *sechdrs, 230 struct module *mod) 231 { 232 return 0; 233 } 234 235 void module_arch_cleanup(struct module *mod) 236 { 237 } 238