debuggers.hg

view xen/common/libelf/libelf-relocate.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents eccfdeb41b80
children
line source
1 /*
2 * ELF relocation code (not used by xen kernel right now).
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
19 #include "libelf-private.h"
21 /* ------------------------------------------------------------------------ */
23 static const char *rel_names_i386[] = {
24 "R_386_NONE",
25 "R_386_32",
26 "R_386_PC32",
27 "R_386_GOT32",
28 "R_386_PLT32",
29 "R_386_COPY",
30 "R_386_GLOB_DAT",
31 "R_386_JMP_SLOT",
32 "R_386_RELATIVE",
33 "R_386_GOTOFF",
34 "R_386_GOTPC",
35 "R_386_32PLT",
36 "R_386_TLS_TPOFF",
37 "R_386_TLS_IE",
38 "R_386_TLS_GOTIE",
39 "R_386_TLS_LE",
40 "R_386_TLS_GD",
41 "R_386_TLS_LDM",
42 "R_386_16",
43 "R_386_PC16",
44 "R_386_8",
45 "R_386_PC8",
46 "R_386_TLS_GD_32",
47 "R_386_TLS_GD_PUSH",
48 "R_386_TLS_GD_CALL",
49 "R_386_TLS_GD_POP",
50 "R_386_TLS_LDM_32",
51 "R_386_TLS_LDM_PUSH",
52 "R_386_TLS_LDM_CALL",
53 "R_386_TLS_LDM_POP",
54 "R_386_TLS_LDO_32",
55 "R_386_TLS_IE_32",
56 "R_386_TLS_LE_32",
57 "R_386_TLS_DTPMOD32",
58 "R_386_TLS_DTPOFF32",
59 "R_386_TLS_TPOFF32",
60 };
62 static int elf_reloc_i386(struct elf_binary *elf, int type,
63 uint64_t addr, uint64_t value)
64 {
65 void *ptr = elf_get_ptr(elf, addr);
66 uint32_t *u32;
68 switch ( type )
69 {
70 case 1 /* R_386_32 */ :
71 u32 = ptr;
72 *u32 += elf->reloc_offset;
73 break;
74 case 2 /* R_386_PC32 */ :
75 /* nothing */
76 break;
77 default:
78 return -1;
79 }
80 return 0;
81 }
83 /* ------------------------------------------------------------------------ */
85 static const char *rel_names_x86_64[] = {
86 "R_X86_64_NONE",
87 "R_X86_64_64",
88 "R_X86_64_PC32",
89 "R_X86_64_GOT32",
90 "R_X86_64_PLT32",
91 "R_X86_64_COPY",
92 "R_X86_64_GLOB_DAT",
93 "R_X86_64_JUMP_SLOT",
94 "R_X86_64_RELATIVE",
95 "R_X86_64_GOTPCREL",
96 "R_X86_64_32",
97 "R_X86_64_32S",
98 "R_X86_64_16",
99 "R_X86_64_PC16",
100 "R_X86_64_8",
101 "R_X86_64_PC8",
102 "R_X86_64_DTPMOD64",
103 "R_X86_64_DTPOFF64",
104 "R_X86_64_TPOFF64",
105 "R_X86_64_TLSGD",
106 "R_X86_64_TLSLD",
107 "R_X86_64_DTPOFF32",
108 "R_X86_64_GOTTPOFF",
109 "R_X86_64_TPOFF32",
110 };
112 static int elf_reloc_x86_64(struct elf_binary *elf, int type,
113 uint64_t addr, uint64_t value)
114 {
115 void *ptr = elf_get_ptr(elf, addr);
116 uint64_t *u64;
117 uint32_t *u32;
118 int32_t *s32;
120 switch ( type )
121 {
122 case 1 /* R_X86_64_64 */ :
123 u64 = ptr;
124 value += elf->reloc_offset;
125 *u64 = value;
126 break;
127 case 2 /* R_X86_64_PC32 */ :
128 u32 = ptr;
129 *u32 = value - addr;
130 if ( *u32 != (uint32_t)(value - addr) )
131 {
132 elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
133 " != 0x%" PRIx32 "\n",
134 *u32, (uint32_t) (value - addr));
135 return -1;
136 }
137 break;
138 case 10 /* R_X86_64_32 */ :
139 u32 = ptr;
140 value += elf->reloc_offset;
141 *u32 = value;
142 if ( *u32 != value )
143 {
144 elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
145 " != 0x%" PRIx64 "\n",
146 *u32, value);
147 return -1;
148 }
149 break;
150 case 11 /* R_X86_64_32S */ :
151 s32 = ptr;
152 value += elf->reloc_offset;
153 *s32 = value;
154 if ( *s32 != (int64_t) value )
155 {
156 elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
157 " != 0x%" PRIx64 "\n",
158 *s32, (int64_t) value);
159 return -1;
160 }
161 break;
162 default:
163 return -1;
164 }
165 return 0;
166 }
168 /* ------------------------------------------------------------------------ */
170 static struct relocs {
171 const char **names;
172 int count;
173 int (*func) (struct elf_binary * elf, int type, uint64_t addr,
174 uint64_t value);
175 } relocs[] =
176 /* *INDENT-OFF* */
177 {
178 [EM_386] = {
179 .names = rel_names_i386,
180 .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
181 .func = elf_reloc_i386,
182 },
183 [EM_X86_64] = {
184 .names = rel_names_x86_64,
185 .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
186 .func = elf_reloc_x86_64,
187 }
188 };
189 /* *INDENT-ON* */
191 /* ------------------------------------------------------------------------ */
193 static const char *rela_name(int machine, int type)
194 {
195 if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
196 return "unknown mach";
197 if ( !relocs[machine].names )
198 return "unknown mach";
199 if ( type > relocs[machine].count )
200 return "unknown rela";
201 return relocs[machine].names[type];
202 }
204 static int elf_reloc_section(struct elf_binary *elf,
205 const elf_shdr * rels,
206 const elf_shdr * sect, const elf_shdr * syms)
207 {
208 const void *ptr, *end;
209 const elf_shdr *shdr;
210 const elf_rela *rela;
211 const elf_rel *rel;
212 const elf_sym *sym;
213 uint64_t s_type;
214 uint64_t r_offset;
215 uint64_t r_info;
216 uint64_t r_addend;
217 int r_type, r_sym;
218 size_t rsize;
219 uint64_t shndx, sbase, addr, value;
220 const char *sname;
221 int machine;
223 machine = elf_uval(elf, elf->ehdr, e_machine);
224 if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
225 (relocs[machine].func == NULL) )
226 {
227 elf_err(elf, "%s: can't handle machine %d\n",
228 __FUNCTION__, machine);
229 return -1;
230 }
231 if ( elf_swap(elf) )
232 {
233 elf_err(elf, "%s: non-native byte order, relocation not supported\n",
234 __FUNCTION__);
235 return -1;
236 }
238 s_type = elf_uval(elf, rels, sh_type);
239 rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
240 ptr = elf_section_start(elf, rels);
241 end = elf_section_end(elf, rels);
243 for ( ; ptr < end; ptr += rsize )
244 {
245 switch ( s_type )
246 {
247 case SHT_REL:
248 rel = ptr;
249 r_offset = elf_uval(elf, rel, r_offset);
250 r_info = elf_uval(elf, rel, r_info);
251 r_addend = 0;
252 break;
253 case SHT_RELA:
254 rela = ptr;
255 r_offset = elf_uval(elf, rela, r_offset);
256 r_info = elf_uval(elf, rela, r_info);
257 r_addend = elf_uval(elf, rela, r_addend);
258 break;
259 default:
260 /* can't happen */
261 return -1;
262 }
263 if ( elf_64bit(elf) )
264 {
265 r_type = ELF64_R_TYPE(r_info);
266 r_sym = ELF64_R_SYM(r_info);
267 }
268 else
269 {
270 r_type = ELF32_R_TYPE(r_info);
271 r_sym = ELF32_R_SYM(r_info);
272 }
274 sym = elf_sym_by_index(elf, r_sym);
275 shndx = elf_uval(elf, sym, st_shndx);
276 switch ( shndx )
277 {
278 case SHN_UNDEF:
279 sname = "*UNDEF*";
280 sbase = 0;
281 break;
282 case SHN_COMMON:
283 elf_err(elf, "%s: invalid section: %" PRId64 "\n",
284 __FUNCTION__, shndx);
285 return -1;
286 case SHN_ABS:
287 sname = "*ABS*";
288 sbase = 0;
289 break;
290 default:
291 shdr = elf_shdr_by_index(elf, shndx);
292 if ( shdr == NULL )
293 {
294 elf_err(elf, "%s: invalid section: %" PRId64 "\n",
295 __FUNCTION__, shndx);
296 return -1;
297 }
298 sname = elf_section_name(elf, shdr);
299 sbase = elf_uval(elf, shdr, sh_addr);
300 }
302 addr = r_offset;
303 value = elf_uval(elf, sym, st_value);
304 value += r_addend;
306 if ( elf->log_callback && (elf->verbose > 1) )
307 {
308 uint64_t st_name = elf_uval(elf, sym, st_name);
309 const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
311 elf_msg(elf,
312 "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
313 " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
314 " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
315 __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
316 r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
317 addr, value);
318 }
320 if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
321 {
322 elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
323 __FUNCTION__, rela_name(machine, r_type), r_type);
324 return -1;
325 }
326 }
327 return 0;
328 }
330 int elf_reloc(struct elf_binary *elf)
331 {
332 const elf_shdr *rels, *sect, *syms;
333 uint64_t i, count, type;
335 count = elf_shdr_count(elf);
336 for ( i = 0; i < count; i++ )
337 {
338 rels = elf_shdr_by_index(elf, i);
339 type = elf_uval(elf, rels, sh_type);
340 if ( (type != SHT_REL) && (type != SHT_RELA) )
341 continue;
343 sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
344 syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
345 if ( NULL == sect || NULL == syms )
346 continue;
348 if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
349 {
350 elf_msg(elf, "%s: relocations for %s, skipping\n",
351 __FUNCTION__, elf_section_name(elf, sect));
352 continue;
353 }
355 elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
356 __FUNCTION__, elf_section_name(elf, sect),
357 elf_uval(elf, sect, sh_addr));
358 if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
359 return -1;
360 }
361 return 0;
362 }
364 /*
365 * Local variables:
366 * mode: C
367 * c-set-style: "BSD"
368 * c-basic-offset: 4
369 * tab-width: 4
370 * indent-tabs-mode: nil
371 * End:
372 */