module.c 5.8 KB

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