Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
module.c
Go to the documentation of this file.
1 /*
2  * AArch64 loadable module support.
3  *
4  * Copyright (C) 2012 ARM Limited
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Will Deacon <[email protected]>
19  */
20 
21 #include <linux/bitops.h>
22 #include <linux/elf.h>
23 #include <linux/gfp.h>
24 #include <linux/kernel.h>
25 #include <linux/mm.h>
26 #include <linux/moduleloader.h>
27 #include <linux/vmalloc.h>
28 
29 void *module_alloc(unsigned long size)
30 {
33  __builtin_return_address(0));
34 }
35 
41 };
42 
43 static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val)
44 {
45  switch (reloc_op) {
46  case RELOC_OP_ABS:
47  return val;
48  case RELOC_OP_PREL:
49  return val - (u64)place;
50  case RELOC_OP_PAGE:
51  return (val & ~0xfff) - ((u64)place & ~0xfff);
52  case RELOC_OP_NONE:
53  return 0;
54  }
55 
56  pr_err("do_reloc: unknown relocation operation %d\n", reloc_op);
57  return 0;
58 }
59 
60 static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
61 {
62  u64 imm_mask = (1 << len) - 1;
63  s64 sval = do_reloc(op, place, val);
64 
65  switch (len) {
66  case 16:
67  *(s16 *)place = sval;
68  break;
69  case 32:
70  *(s32 *)place = sval;
71  break;
72  case 64:
73  *(s64 *)place = sval;
74  break;
75  default:
76  pr_err("Invalid length (%d) for data relocation\n", len);
77  return 0;
78  }
79 
80  /*
81  * Extract the upper value bits (including the sign bit) and
82  * shift them to bit 0.
83  */
84  sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
85 
86  /*
87  * Overflow has occurred if the value is not representable in
88  * len bits (i.e the bottom len bits are not sign-extended and
89  * the top bits are not all zero).
90  */
91  if ((u64)(sval + 1) > 2)
92  return -ERANGE;
93 
94  return 0;
95 }
96 
107 };
108 
109 static u32 encode_insn_immediate(enum aarch64_imm_type type, u32 insn, u64 imm)
110 {
111  u32 immlo, immhi, lomask, himask, mask;
112  int shift;
113 
114  switch (type) {
115  case INSN_IMM_MOVNZ:
116  /*
117  * For signed MOVW relocations, we have to manipulate the
118  * instruction encoding depending on whether or not the
119  * immediate is less than zero.
120  */
121  insn &= ~(3 << 29);
122  if ((s64)imm >= 0) {
123  /* >=0: Set the instruction to MOVZ (opcode 10b). */
124  insn |= 2 << 29;
125  } else {
126  /*
127  * <0: Set the instruction to MOVN (opcode 00b).
128  * Since we've masked the opcode already, we
129  * don't need to do anything other than
130  * inverting the new immediate field.
131  */
132  imm = ~imm;
133  }
134  case INSN_IMM_MOVK:
135  mask = BIT(16) - 1;
136  shift = 5;
137  break;
138  case INSN_IMM_ADR:
139  lomask = 0x3;
140  himask = 0x7ffff;
141  immlo = imm & lomask;
142  imm >>= 2;
143  immhi = imm & himask;
144  imm = (immlo << 24) | (immhi);
145  mask = (lomask << 24) | (himask);
146  shift = 5;
147  break;
148  case INSN_IMM_26:
149  mask = BIT(26) - 1;
150  shift = 0;
151  break;
152  case INSN_IMM_19:
153  mask = BIT(19) - 1;
154  shift = 5;
155  break;
156  case INSN_IMM_16:
157  mask = BIT(16) - 1;
158  shift = 5;
159  break;
160  case INSN_IMM_14:
161  mask = BIT(14) - 1;
162  shift = 5;
163  break;
164  case INSN_IMM_12:
165  mask = BIT(12) - 1;
166  shift = 10;
167  break;
168  case INSN_IMM_9:
169  mask = BIT(9) - 1;
170  shift = 12;
171  break;
172  default:
173  pr_err("encode_insn_immediate: unknown immediate encoding %d\n",
174  type);
175  return 0;
176  }
177 
178  /* Update the immediate field. */
179  insn &= ~(mask << shift);
180  insn |= (imm & mask) << shift;
181 
182  return insn;
183 }
184 
185 static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val,
186  int lsb, enum aarch64_imm_type imm_type)
187 {
188  u64 imm, limit = 0;
189  s64 sval;
190  u32 insn = *(u32 *)place;
191 
192  sval = do_reloc(op, place, val);
193  sval >>= lsb;
194  imm = sval & 0xffff;
195 
196  /* Update the instruction with the new encoding. */
197  *(u32 *)place = encode_insn_immediate(imm_type, insn, imm);
198 
199  /* Shift out the immediate field. */
200  sval >>= 16;
201 
202  /*
203  * For unsigned immediates, the overflow check is straightforward.
204  * For signed immediates, the sign bit is actually the bit past the
205  * most significant bit of the field.
206  * The INSN_IMM_16 immediate type is unsigned.
207  */
208  if (imm_type != INSN_IMM_16) {
209  sval++;
210  limit++;
211  }
212 
213  /* Check the upper bits depending on the sign of the immediate. */
214  if ((u64)sval > limit)
215  return -ERANGE;
216 
217  return 0;
218 }
219 
220 static int reloc_insn_imm(enum aarch64_reloc_op op, void *place, u64 val,
221  int lsb, int len, enum aarch64_imm_type imm_type)
222 {
223  u64 imm, imm_mask;
224  s64 sval;
225  u32 insn = *(u32 *)place;
226 
227  /* Calculate the relocation value. */
228  sval = do_reloc(op, place, val);
229  sval >>= lsb;
230 
231  /* Extract the value bits and shift them to bit 0. */
232  imm_mask = (BIT(lsb + len) - 1) >> lsb;
233  imm = sval & imm_mask;
234 
235  /* Update the instruction's immediate field. */
236  *(u32 *)place = encode_insn_immediate(imm_type, insn, imm);
237 
238  /*
239  * Extract the upper value bits (including the sign bit) and
240  * shift them to bit 0.
241  */
242  sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
243 
244  /*
245  * Overflow has occurred if the upper bits are not all equal to
246  * the sign bit of the value.
247  */
248  if ((u64)(sval + 1) >= 2)
249  return -ERANGE;
250 
251  return 0;
252 }
253 
255  const char *strtab,
256  unsigned int symindex,
257  unsigned int relsec,
258  struct module *me)
259 {
260  unsigned int i;
261  int ovf;
262  bool overflow_check;
263  Elf64_Sym *sym;
264  void *loc;
265  u64 val;
266  Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
267 
268  for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
269  /* loc corresponds to P in the AArch64 ELF document. */
270  loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
271  + rel[i].r_offset;
272 
273  /* sym is the ELF symbol we're referring to. */
274  sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
275  + ELF64_R_SYM(rel[i].r_info);
276 
277  /* val corresponds to (S + A) in the AArch64 ELF document. */
278  val = sym->st_value + rel[i].r_addend;
279 
280  /* Check for overflow by default. */
281  overflow_check = true;
282 
283  /* Perform the static relocation. */
284  switch (ELF64_R_TYPE(rel[i].r_info)) {
285  /* Null relocations. */
286  case R_ARM_NONE:
287  case R_AARCH64_NONE:
288  ovf = 0;
289  break;
290 
291  /* Data relocations. */
292  case R_AARCH64_ABS64:
293  overflow_check = false;
294  ovf = reloc_data(RELOC_OP_ABS, loc, val, 64);
295  break;
296  case R_AARCH64_ABS32:
297  ovf = reloc_data(RELOC_OP_ABS, loc, val, 32);
298  break;
299  case R_AARCH64_ABS16:
300  ovf = reloc_data(RELOC_OP_ABS, loc, val, 16);
301  break;
302  case R_AARCH64_PREL64:
303  overflow_check = false;
304  ovf = reloc_data(RELOC_OP_PREL, loc, val, 64);
305  break;
306  case R_AARCH64_PREL32:
307  ovf = reloc_data(RELOC_OP_PREL, loc, val, 32);
308  break;
309  case R_AARCH64_PREL16:
310  ovf = reloc_data(RELOC_OP_PREL, loc, val, 16);
311  break;
312 
313  /* MOVW instruction relocations. */
315  overflow_check = false;
317  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
318  INSN_IMM_16);
319  break;
321  overflow_check = false;
323  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
324  INSN_IMM_16);
325  break;
327  overflow_check = false;
329  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
330  INSN_IMM_16);
331  break;
333  /* We're using the top bits so we can't overflow. */
334  overflow_check = false;
335  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48,
336  INSN_IMM_16);
337  break;
339  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
341  break;
343  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
345  break;
347  ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
349  break;
351  overflow_check = false;
352  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
353  INSN_IMM_MOVK);
354  break;
356  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
358  break;
360  overflow_check = false;
361  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
362  INSN_IMM_MOVK);
363  break;
365  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
367  break;
369  overflow_check = false;
370  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
371  INSN_IMM_MOVK);
372  break;
374  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
376  break;
378  /* We're using the top bits so we can't overflow. */
379  overflow_check = false;
380  ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48,
382  break;
383 
384  /* Immediate instruction relocations. */
386  ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
387  INSN_IMM_19);
388  break;
390  ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21,
391  INSN_IMM_ADR);
392  break;
394  overflow_check = false;
396  ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21,
397  INSN_IMM_ADR);
398  break;
401  overflow_check = false;
402  ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12,
403  INSN_IMM_12);
404  break;
406  overflow_check = false;
407  ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11,
408  INSN_IMM_12);
409  break;
411  overflow_check = false;
412  ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10,
413  INSN_IMM_12);
414  break;
416  overflow_check = false;
417  ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9,
418  INSN_IMM_12);
419  break;
421  overflow_check = false;
422  ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8,
423  INSN_IMM_12);
424  break;
425  case R_AARCH64_TSTBR14:
426  ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14,
427  INSN_IMM_14);
428  break;
429  case R_AARCH64_CONDBR19:
430  ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
431  INSN_IMM_19);
432  break;
433  case R_AARCH64_JUMP26:
434  case R_AARCH64_CALL26:
435  ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26,
436  INSN_IMM_26);
437  break;
438 
439  default:
440  pr_err("module %s: unsupported RELA relocation: %llu\n",
441  me->name, ELF64_R_TYPE(rel[i].r_info));
442  return -ENOEXEC;
443  }
444 
445  if (overflow_check && ovf == -ERANGE)
446  goto overflow;
447 
448  }
449 
450  return 0;
451 
452 overflow:
453  pr_err("module %s: overflow in relocation type %d val %Lx\n",
454  me->name, (int)ELF64_R_TYPE(rel[i].r_info), val);
455  return -ENOEXEC;
456 }