module.c 4.9 KB

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