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