module.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /* Kernel module help for Meta.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. */
  11. #include <linux/moduleloader.h>
  12. #include <linux/elf.h>
  13. #include <linux/vmalloc.h>
  14. #include <linux/fs.h>
  15. #include <linux/string.h>
  16. #include <linux/kernel.h>
  17. #include <linux/sort.h>
  18. #include <asm/unaligned.h>
  19. /* Count how many different relocations (different symbol, different
  20. addend) */
  21. static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
  22. {
  23. unsigned int i, r_info, r_addend, _count_relocs;
  24. _count_relocs = 0;
  25. r_info = 0;
  26. r_addend = 0;
  27. for (i = 0; i < num; i++)
  28. /* Only count relbranch relocs, others don't need stubs */
  29. if (ELF32_R_TYPE(rela[i].r_info) == R_METAG_RELBRANCH &&
  30. (r_info != ELF32_R_SYM(rela[i].r_info) ||
  31. r_addend != rela[i].r_addend)) {
  32. _count_relocs++;
  33. r_info = ELF32_R_SYM(rela[i].r_info);
  34. r_addend = rela[i].r_addend;
  35. }
  36. return _count_relocs;
  37. }
  38. static int relacmp(const void *_x, const void *_y)
  39. {
  40. const Elf32_Rela *x, *y;
  41. y = (Elf32_Rela *)_x;
  42. x = (Elf32_Rela *)_y;
  43. /* Compare the entire r_info (as opposed to ELF32_R_SYM(r_info) only) to
  44. * make the comparison cheaper/faster. It won't affect the sorting or
  45. * the counting algorithms' performance
  46. */
  47. if (x->r_info < y->r_info)
  48. return -1;
  49. else if (x->r_info > y->r_info)
  50. return 1;
  51. else if (x->r_addend < y->r_addend)
  52. return -1;
  53. else if (x->r_addend > y->r_addend)
  54. return 1;
  55. else
  56. return 0;
  57. }
  58. static void relaswap(void *_x, void *_y, int size)
  59. {
  60. uint32_t *x, *y, tmp;
  61. int i;
  62. y = (uint32_t *)_x;
  63. x = (uint32_t *)_y;
  64. for (i = 0; i < sizeof(Elf32_Rela) / sizeof(uint32_t); i++) {
  65. tmp = x[i];
  66. x[i] = y[i];
  67. y[i] = tmp;
  68. }
  69. }
  70. /* Get the potential trampolines size required of the init and
  71. non-init sections */
  72. static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
  73. const Elf32_Shdr *sechdrs,
  74. const char *secstrings,
  75. int is_init)
  76. {
  77. unsigned long ret = 0;
  78. unsigned i;
  79. /* Everything marked ALLOC (this includes the exported
  80. symbols) */
  81. for (i = 1; i < hdr->e_shnum; i++) {
  82. /* If it's called *.init*, and we're not init, we're
  83. not interested */
  84. if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != NULL)
  85. != is_init)
  86. continue;
  87. /* We don't want to look at debug sections. */
  88. if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != NULL)
  89. continue;
  90. if (sechdrs[i].sh_type == SHT_RELA) {
  91. pr_debug("Found relocations in section %u\n", i);
  92. pr_debug("Ptr: %p. Number: %u\n",
  93. (void *)hdr + sechdrs[i].sh_offset,
  94. sechdrs[i].sh_size / sizeof(Elf32_Rela));
  95. /* Sort the relocation information based on a symbol and
  96. * addend key. This is a stable O(n*log n) complexity
  97. * alogrithm but it will reduce the complexity of
  98. * count_relocs() to linear complexity O(n)
  99. */
  100. sort((void *)hdr + sechdrs[i].sh_offset,
  101. sechdrs[i].sh_size / sizeof(Elf32_Rela),
  102. sizeof(Elf32_Rela), relacmp, relaswap);
  103. ret += count_relocs((void *)hdr
  104. + sechdrs[i].sh_offset,
  105. sechdrs[i].sh_size
  106. / sizeof(Elf32_Rela))
  107. * sizeof(struct metag_plt_entry);
  108. }
  109. }
  110. return ret;
  111. }
  112. int module_frob_arch_sections(Elf32_Ehdr *hdr,
  113. Elf32_Shdr *sechdrs,
  114. char *secstrings,
  115. struct module *me)
  116. {
  117. unsigned int i;
  118. /* Find .plt and .init.plt sections */
  119. for (i = 0; i < hdr->e_shnum; i++) {
  120. if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
  121. me->arch.init_plt_section = i;
  122. else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
  123. me->arch.core_plt_section = i;
  124. }
  125. if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
  126. pr_err("Module doesn't contain .plt or .init.plt sections.\n");
  127. return -ENOEXEC;
  128. }
  129. /* Override their sizes */
  130. sechdrs[me->arch.core_plt_section].sh_size
  131. = get_plt_size(hdr, sechdrs, secstrings, 0);
  132. sechdrs[me->arch.core_plt_section].sh_type = SHT_NOBITS;
  133. sechdrs[me->arch.init_plt_section].sh_size
  134. = get_plt_size(hdr, sechdrs, secstrings, 1);
  135. sechdrs[me->arch.init_plt_section].sh_type = SHT_NOBITS;
  136. return 0;
  137. }
  138. /* Set up a trampoline in the PLT to bounce us to the distant function */
  139. static uint32_t do_plt_call(void *location, Elf32_Addr val,
  140. Elf32_Shdr *sechdrs, struct module *mod)
  141. {
  142. struct metag_plt_entry *entry;
  143. /* Instructions used to do the indirect jump. */
  144. uint32_t tramp[2];
  145. /* We have to trash a register, so we assume that any control
  146. transfer more than 21-bits away must be a function call
  147. (so we can use a call-clobbered register). */
  148. /* MOVT D0Re0,#HI(v) */
  149. tramp[0] = 0x02000005 | (((val & 0xffff0000) >> 16) << 3);
  150. /* JUMP D0Re0,#LO(v) */
  151. tramp[1] = 0xac000001 | ((val & 0x0000ffff) << 3);
  152. /* Init, or core PLT? */
  153. if (location >= mod->module_core
  154. && location < mod->module_core + mod->core_size)
  155. entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
  156. else
  157. entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
  158. /* Find this entry, or if that fails, the next avail. entry */
  159. while (entry->tramp[0])
  160. if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1])
  161. return (uint32_t)entry;
  162. else
  163. entry++;
  164. entry->tramp[0] = tramp[0];
  165. entry->tramp[1] = tramp[1];
  166. return (uint32_t)entry;
  167. }
  168. int apply_relocate_add(Elf32_Shdr *sechdrs,
  169. const char *strtab,
  170. unsigned int symindex,
  171. unsigned int relsec,
  172. struct module *me)
  173. {
  174. unsigned int i;
  175. Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
  176. Elf32_Sym *sym;
  177. Elf32_Addr relocation;
  178. uint32_t *location;
  179. int32_t value;
  180. pr_debug("Applying relocate section %u to %u\n", relsec,
  181. sechdrs[relsec].sh_info);
  182. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
  183. /* This is where to make the change */
  184. location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
  185. + rel[i].r_offset;
  186. /* This is the symbol it is referring to. Note that all
  187. undefined symbols have been resolved. */
  188. sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
  189. + ELF32_R_SYM(rel[i].r_info);
  190. relocation = sym->st_value + rel[i].r_addend;
  191. switch (ELF32_R_TYPE(rel[i].r_info)) {
  192. case R_METAG_NONE:
  193. break;
  194. case R_METAG_HIADDR16:
  195. relocation >>= 16;
  196. case R_METAG_LOADDR16:
  197. *location = (*location & 0xfff80007) |
  198. ((relocation & 0xffff) << 3);
  199. break;
  200. case R_METAG_ADDR32:
  201. /*
  202. * Packed data structures may cause a misaligned
  203. * R_METAG_ADDR32 to be emitted.
  204. */
  205. put_unaligned(relocation, location);
  206. break;
  207. case R_METAG_GETSETOFF:
  208. *location += ((relocation & 0xfff) << 7);
  209. break;
  210. case R_METAG_RELBRANCH:
  211. if (*location & (0x7ffff << 5)) {
  212. pr_err("bad relbranch relocation\n");
  213. break;
  214. }
  215. /* This jump is too big for the offset slot. Build
  216. * a PLT to jump through to get to where we want to go.
  217. * NB: 21bit check - not scaled to 19bit yet
  218. */
  219. if (((int32_t)(relocation -
  220. (uint32_t)location) > 0xfffff) ||
  221. ((int32_t)(relocation -
  222. (uint32_t)location) < -0xfffff)) {
  223. relocation = do_plt_call(location, relocation,
  224. sechdrs, me);
  225. }
  226. value = relocation - (uint32_t)location;
  227. /* branch instruction aligned */
  228. value /= 4;
  229. if ((value > 0x7ffff) || (value < -0x7ffff)) {
  230. /*
  231. * this should have been caught by the code
  232. * above!
  233. */
  234. pr_err("overflow of relbranch reloc\n");
  235. }
  236. *location = (*location & (~(0x7ffff << 5))) |
  237. ((value & 0x7ffff) << 5);
  238. break;
  239. default:
  240. pr_err("module %s: Unknown relocation: %u\n",
  241. me->name, ELF32_R_TYPE(rel[i].r_info));
  242. return -ENOEXEC;
  243. }
  244. }
  245. return 0;
  246. }