module.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Kernel module help for Alpha.
  3. Copyright (C) 2002 Richard Henderson.
  4. */
  5. #include <linux/moduleloader.h>
  6. #include <linux/elf.h>
  7. #include <linux/vmalloc.h>
  8. #include <linux/fs.h>
  9. #include <linux/string.h>
  10. #include <linux/kernel.h>
  11. #include <linux/slab.h>
  12. #if 0
  13. #define DEBUGP printk
  14. #else
  15. #define DEBUGP(fmt...)
  16. #endif
  17. /* Allocate the GOT at the end of the core sections. */
  18. struct got_entry {
  19. struct got_entry *next;
  20. Elf64_Sxword r_addend;
  21. int got_offset;
  22. };
  23. static inline void
  24. process_reloc_for_got(Elf64_Rela *rela,
  25. struct got_entry *chains, Elf64_Xword *poffset)
  26. {
  27. unsigned long r_sym = ELF64_R_SYM (rela->r_info);
  28. unsigned long r_type = ELF64_R_TYPE (rela->r_info);
  29. Elf64_Sxword r_addend = rela->r_addend;
  30. struct got_entry *g;
  31. if (r_type != R_ALPHA_LITERAL)
  32. return;
  33. for (g = chains + r_sym; g ; g = g->next)
  34. if (g->r_addend == r_addend) {
  35. if (g->got_offset == 0) {
  36. g->got_offset = *poffset;
  37. *poffset += 8;
  38. }
  39. goto found_entry;
  40. }
  41. g = kmalloc (sizeof (*g), GFP_KERNEL);
  42. g->next = chains[r_sym].next;
  43. g->r_addend = r_addend;
  44. g->got_offset = *poffset;
  45. *poffset += 8;
  46. chains[r_sym].next = g;
  47. found_entry:
  48. /* Trick: most of the ELF64_R_TYPE field is unused. There are
  49. 42 valid relocation types, and a 32-bit field. Co-opt the
  50. bits above 256 to store the got offset for this reloc. */
  51. rela->r_info |= g->got_offset << 8;
  52. }
  53. int
  54. module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
  55. char *secstrings, struct module *me)
  56. {
  57. struct got_entry *chains;
  58. Elf64_Rela *rela;
  59. Elf64_Shdr *esechdrs, *symtab, *s, *got;
  60. unsigned long nsyms, nrela, i;
  61. esechdrs = sechdrs + hdr->e_shnum;
  62. symtab = got = NULL;
  63. /* Find out how large the symbol table is. Allocate one got_entry
  64. head per symbol. Normally this will be enough, but not always.
  65. We'll chain different offsets for the symbol down each head. */
  66. for (s = sechdrs; s < esechdrs; ++s)
  67. if (s->sh_type == SHT_SYMTAB)
  68. symtab = s;
  69. else if (!strcmp(".got", secstrings + s->sh_name)) {
  70. got = s;
  71. me->arch.gotsecindex = s - sechdrs;
  72. }
  73. if (!symtab) {
  74. printk(KERN_ERR "module %s: no symbol table\n", me->name);
  75. return -ENOEXEC;
  76. }
  77. if (!got) {
  78. printk(KERN_ERR "module %s: no got section\n", me->name);
  79. return -ENOEXEC;
  80. }
  81. nsyms = symtab->sh_size / sizeof(Elf64_Sym);
  82. chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL);
  83. if (!chains) {
  84. printk(KERN_ERR
  85. "module %s: no memory for symbol chain buffer\n",
  86. me->name);
  87. return -ENOMEM;
  88. }
  89. got->sh_size = 0;
  90. got->sh_addralign = 8;
  91. got->sh_type = SHT_NOBITS;
  92. /* Examine all LITERAL relocations to find out what GOT entries
  93. are required. This sizes the GOT section as well. */
  94. for (s = sechdrs; s < esechdrs; ++s)
  95. if (s->sh_type == SHT_RELA) {
  96. nrela = s->sh_size / sizeof(Elf64_Rela);
  97. rela = (void *)hdr + s->sh_offset;
  98. for (i = 0; i < nrela; ++i)
  99. process_reloc_for_got(rela+i, chains,
  100. &got->sh_size);
  101. }
  102. /* Free the memory we allocated. */
  103. for (i = 0; i < nsyms; ++i) {
  104. struct got_entry *g, *n;
  105. for (g = chains[i].next; g ; g = n) {
  106. n = g->next;
  107. kfree(g);
  108. }
  109. }
  110. kfree(chains);
  111. return 0;
  112. }
  113. int
  114. apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
  115. unsigned int symindex, unsigned int relsec,
  116. struct module *me)
  117. {
  118. Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
  119. unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela);
  120. Elf64_Sym *symtab, *sym;
  121. void *base, *location;
  122. unsigned long got, gp;
  123. DEBUGP("Applying relocate section %u to %u\n", relsec,
  124. sechdrs[relsec].sh_info);
  125. base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
  126. symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
  127. got = sechdrs[me->arch.gotsecindex].sh_addr;
  128. gp = got + 0x8000;
  129. for (i = 0; i < n; i++) {
  130. unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
  131. unsigned long r_type = ELF64_R_TYPE (rela[i].r_info);
  132. unsigned long r_got_offset = r_type >> 8;
  133. unsigned long value, hi, lo;
  134. r_type &= 0xff;
  135. /* This is where to make the change. */
  136. location = base + rela[i].r_offset;
  137. /* This is the symbol it is referring to. Note that all
  138. unresolved symbols have been resolved. */
  139. sym = symtab + r_sym;
  140. value = sym->st_value + rela[i].r_addend;
  141. switch (r_type) {
  142. case R_ALPHA_NONE:
  143. break;
  144. case R_ALPHA_REFLONG:
  145. *(u32 *)location = value;
  146. break;
  147. case R_ALPHA_REFQUAD:
  148. /* BUG() can produce misaligned relocations. */
  149. ((u32 *)location)[0] = value;
  150. ((u32 *)location)[1] = value >> 32;
  151. break;
  152. case R_ALPHA_GPREL32:
  153. value -= gp;
  154. if ((int)value != value)
  155. goto reloc_overflow;
  156. *(u32 *)location = value;
  157. break;
  158. case R_ALPHA_LITERAL:
  159. hi = got + r_got_offset;
  160. lo = hi - gp;
  161. if ((short)lo != lo)
  162. goto reloc_overflow;
  163. *(u16 *)location = lo;
  164. *(u64 *)hi = value;
  165. break;
  166. case R_ALPHA_LITUSE:
  167. break;
  168. case R_ALPHA_GPDISP:
  169. value = gp - (u64)location;
  170. lo = (short)value;
  171. hi = (int)(value - lo);
  172. if (hi + lo != value)
  173. goto reloc_overflow;
  174. *(u16 *)location = hi >> 16;
  175. *(u16 *)(location + rela[i].r_addend) = lo;
  176. break;
  177. case R_ALPHA_BRSGP:
  178. /* BRSGP is only allowed to bind to local symbols.
  179. If the section is undef, this means that the
  180. value was resolved from somewhere else. */
  181. if (sym->st_shndx == SHN_UNDEF)
  182. goto reloc_overflow;
  183. if ((sym->st_other & STO_ALPHA_STD_GPLOAD) ==
  184. STO_ALPHA_STD_GPLOAD)
  185. /* Omit the prologue. */
  186. value += 8;
  187. fallthrough;
  188. case R_ALPHA_BRADDR:
  189. value -= (u64)location + 4;
  190. if (value & 3)
  191. goto reloc_overflow;
  192. value = (long)value >> 2;
  193. if (value + (1<<21) >= 1<<22)
  194. goto reloc_overflow;
  195. value &= 0x1fffff;
  196. value |= *(u32 *)location & ~0x1fffff;
  197. *(u32 *)location = value;
  198. break;
  199. case R_ALPHA_HINT:
  200. break;
  201. case R_ALPHA_SREL32:
  202. value -= (u64)location;
  203. if ((int)value != value)
  204. goto reloc_overflow;
  205. *(u32 *)location = value;
  206. break;
  207. case R_ALPHA_SREL64:
  208. value -= (u64)location;
  209. *(u64 *)location = value;
  210. break;
  211. case R_ALPHA_GPRELHIGH:
  212. value = (long)(value - gp + 0x8000) >> 16;
  213. if ((short) value != value)
  214. goto reloc_overflow;
  215. *(u16 *)location = value;
  216. break;
  217. case R_ALPHA_GPRELLOW:
  218. value -= gp;
  219. *(u16 *)location = value;
  220. break;
  221. case R_ALPHA_GPREL16:
  222. value -= gp;
  223. if ((short) value != value)
  224. goto reloc_overflow;
  225. *(u16 *)location = value;
  226. break;
  227. default:
  228. printk(KERN_ERR "module %s: Unknown relocation: %lu\n",
  229. me->name, r_type);
  230. return -ENOEXEC;
  231. reloc_overflow:
  232. if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION)
  233. printk(KERN_ERR
  234. "module %s: Relocation (type %lu) overflow vs section %d\n",
  235. me->name, r_type, sym->st_shndx);
  236. else
  237. printk(KERN_ERR
  238. "module %s: Relocation (type %lu) overflow vs %s\n",
  239. me->name, r_type, strtab + sym->st_name);
  240. return -ENOEXEC;
  241. }
  242. }
  243. return 0;
  244. }