15a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel/* 2f30c2269544bffc7bf1b0d7c0abe5be1be83b8cbUwe Zeisberger * arch/xtensa/kernel/module.c 35a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * 45a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * Module support. 55a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * 65a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * This file is subject to the terms and conditions of the GNU General Public 75a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * License. See the file "COPYING" in the main directory of this archive 85a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * for more details. 95a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * 10ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel * Copyright (C) 2001 - 2006 Tensilica Inc. 115a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * 125a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * Chris Zankel <chris@zankel.net> 135a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * 145a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel */ 155a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel 165a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/module.h> 175a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/moduleloader.h> 185a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/elf.h> 195a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/vmalloc.h> 205a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/fs.h> 215a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/string.h> 225a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/kernel.h> 235a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/cache.h> 245a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel 25ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#undef DEBUG_RELOCATE 265a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel 27ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankelstatic int 28ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankeldecode_calln_opcode (unsigned char *location) 29ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel{ 30ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__ 31ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return (location[0] & 0xf0) == 0x50; 32ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 33ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__ 34ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return (location[0] & 0xf) == 0x5; 35ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 36ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel} 37ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 38ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankelstatic int 39ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankeldecode_l32r_opcode (unsigned char *location) 40ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel{ 41ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__ 42ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return (location[0] & 0xf0) == 0x10; 43ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 44ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__ 45ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return (location[0] & 0xf) == 0x1; 46ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 475a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel} 485a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel 495a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankelint apply_relocate_add(Elf32_Shdr *sechdrs, 505a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel const char *strtab, 515a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel unsigned int symindex, 525a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel unsigned int relsec, 53ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel struct module *mod) 545a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel{ 55ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel unsigned int i; 56c4c4594b005d89b56964071bbbdeb07daac5bc76Chris Zankel Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 57ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel Elf32_Sym *sym; 58ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel unsigned char *location; 59ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel uint32_t value; 60ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 61ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef DEBUG_RELOCATE 62ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("Applying relocate section %u to %u\n", relsec, 63ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel sechdrs[relsec].sh_info); 64ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 65ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 66ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr 67ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel + rela[i].r_offset; 68ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 69ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel + ELF32_R_SYM(rela[i].r_info); 70ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel value = sym->st_value + rela[i].r_addend; 71ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 72ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel switch (ELF32_R_TYPE(rela[i].r_info)) { 73ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_NONE: 74ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_DIFF8: 75ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_DIFF16: 76ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_DIFF32: 77ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_ASM_EXPAND: 78ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel break; 79ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 80ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_32: 81ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_PLT: 82ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel *(uint32_t *)location += value; 83ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel break; 84ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 85ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT0_OP: 86ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel if (decode_calln_opcode(location)) { 87ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel value -= ((unsigned long)location & -4) + 4; 88ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel if ((value & 3) != 0 || 89ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ((value + (1 << 19)) >> 20) != 0) { 90ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("%s: relocation out of range, " 91ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel "section %d reloc %d " 92ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel "sym '%s'\n", 93ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel mod->name, relsec, i, 94ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel strtab + sym->st_name); 95ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return -ENOEXEC; 96ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } 97ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel value = (signed int)value >> 2; 98ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__ 99ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[0] = ((location[0] & ~0x3) | 100ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ((value >> 16) & 0x3)); 101ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[1] = (value >> 8) & 0xff; 102ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[2] = value & 0xff; 103ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 104ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__ 105ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[0] = ((location[0] & ~0xc0) | 106ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ((value << 6) & 0xc0)); 107ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[1] = (value >> 2) & 0xff; 108ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[2] = (value >> 10) & 0xff; 109ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 110ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } else if (decode_l32r_opcode(location)) { 111ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel value -= (((unsigned long)location + 3) & -4); 112ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel if ((value & 3) != 0 || 113ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel (signed int)value >> 18 != -1) { 114ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("%s: relocation out of range, " 115ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel "section %d reloc %d " 116ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel "sym '%s'\n", 117ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel mod->name, relsec, i, 118ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel strtab + sym->st_name); 119ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return -ENOEXEC; 120ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } 121ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel value = (signed int)value >> 2; 122ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 123ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__ 124ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[1] = (value >> 8) & 0xff; 125ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[2] = value & 0xff; 126ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 127ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__ 128ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[1] = value & 0xff; 129ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel location[2] = (value >> 8) & 0xff; 130ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif 131ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } 132ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel /* FIXME: Ignore any other opcodes. The Xtensa 133ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel assembler currently assumes that the linker will 134ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel always do relaxation and so all PC-relative 135ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel operands need relocations. (The assembler also 136ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel writes out the tentative PC-relative values, 137ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel assuming no link-time relaxation, so it is usually 138ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel safe to ignore the relocations.) If the 139ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel assembler's "--no-link-relax" flag can be made to 140ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel work, and if all kernel modules can be assembled 141ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel with that flag, then unexpected relocations could 142ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel be detected here. */ 143ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel break; 144ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 145ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT1_OP: 146ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT2_OP: 147ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT3_OP: 148ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT4_OP: 149ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT5_OP: 150ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT6_OP: 151ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT7_OP: 152ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT8_OP: 153ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT9_OP: 154ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT10_OP: 155ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT11_OP: 156ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT12_OP: 157ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT13_OP: 158ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT14_OP: 159ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("%s: unexpected FLIX relocation: %u\n", 160ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel mod->name, 161ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ELF32_R_TYPE(rela[i].r_info)); 162ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return -ENOEXEC; 163ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 164ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT0_ALT: 165ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT1_ALT: 166ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT2_ALT: 167ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT3_ALT: 168ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT4_ALT: 169ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT5_ALT: 170ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT6_ALT: 171ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT7_ALT: 172ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT8_ALT: 173ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT9_ALT: 174ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT10_ALT: 175ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT11_ALT: 176ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT12_ALT: 177ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT13_ALT: 178ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel case R_XTENSA_SLOT14_ALT: 179ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("%s: unexpected ALT relocation: %u\n", 180ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel mod->name, 181ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ELF32_R_TYPE(rela[i].r_info)); 182ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return -ENOEXEC; 183ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel 184ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel default: 185ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel printk("%s: unexpected relocation: %u\n", 186ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel mod->name, 187ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel ELF32_R_TYPE(rela[i].r_info)); 188ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return -ENOEXEC; 189ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } 190ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel } 191ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel return 0; 1925a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel} 193