Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : #include <vppinfra/bitmap.h>
16 : #include <vppinfra/byte_order.h>
17 : #include <vppinfra/error.h>
18 : #include <vppinfra/hash.h>
19 : #include <vppinfra/vec.h>
20 : #include <vppinfra/elf.h>
21 :
22 : always_inline void
23 108136 : elf_swap_first_header (elf_main_t * em, elf_first_header_t * h)
24 : {
25 108136 : h->architecture = elf_swap_u16 (em, h->architecture);
26 108136 : h->file_type = elf_swap_u16 (em, h->file_type);
27 108136 : h->file_version = elf_swap_u32 (em, h->file_version);
28 108136 : }
29 :
30 : always_inline void
31 0 : elf_swap_verneed (elf_dynamic_version_need_t * n)
32 : {
33 : #define _(t,f) n->f = clib_byte_swap_##t (n->f);
34 0 : foreach_elf_dynamic_version_need_field
35 : #undef _
36 0 : }
37 :
38 : always_inline void
39 0 : elf_swap_verneed_aux (elf_dynamic_version_need_aux_t * n)
40 : {
41 : #define _(t,f) n->f = clib_byte_swap_##t (n->f);
42 0 : foreach_elf_dynamic_version_need_aux_field
43 : #undef _
44 0 : }
45 :
46 : __clib_export clib_error_t *
47 101200 : elf_get_section_by_name (elf_main_t * em, char *section_name,
48 : elf_section_t ** result)
49 : {
50 : uword *p;
51 :
52 101200 : p = hash_get_mem (em->section_by_name, section_name);
53 101200 : if (!p)
54 50600 : return clib_error_return (0, "no such section `%s'", section_name);
55 :
56 50600 : *result = vec_elt_at_index (em->sections, p[0]);
57 50600 : return 0;
58 : }
59 :
60 : elf_section_t *
61 202400 : elf_get_section_by_start_address_no_check (elf_main_t * em,
62 : uword start_address)
63 : {
64 202400 : uword *p = hash_get (em->section_by_start_address, start_address);
65 202400 : return p ? vec_elt_at_index (em->sections, p[0]) : 0;
66 : }
67 :
68 : __clib_export clib_error_t *
69 202400 : elf_get_section_by_start_address (elf_main_t *em, uword start_address,
70 : elf_section_t **result)
71 : {
72 : elf_section_t *s =
73 202400 : elf_get_section_by_start_address_no_check (em, start_address);
74 202400 : if (!s)
75 0 : return clib_error_return (0, "no section with address 0x%wx",
76 : start_address);
77 202400 : *result = s;
78 202400 : return 0;
79 : }
80 :
81 : static u8 *
82 0 : format_elf_section_type (u8 * s, va_list * args)
83 : {
84 0 : elf_section_type_t type = va_arg (*args, elf_section_type_t);
85 0 : char *t = 0;
86 :
87 0 : switch (type)
88 : {
89 : #define _(f,i) case ELF_SECTION_##f: t = #f; break;
90 0 : foreach_elf_section_type
91 : #undef _
92 : }
93 :
94 0 : if (!t)
95 0 : s = format (s, "unknown 0x%x", type);
96 : else
97 0 : s = format (s, "%s", t);
98 0 : return s;
99 : }
100 :
101 : static u8 *
102 0 : format_elf_section (u8 * s, va_list * args)
103 : {
104 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
105 0 : elf_section_t *es = va_arg (*args, elf_section_t *);
106 0 : elf64_section_header_t *h = &es->header;
107 :
108 0 : if (!h)
109 0 : return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s",
110 : "Name", "Index", "Type", "Size", "Align", "Address",
111 : "File offset");
112 :
113 0 : s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx",
114 : elf_section_name (em, es),
115 : es->index,
116 : format_elf_section_type, h->type,
117 : h->file_size,
118 : h->align,
119 0 : h->exec_address, h->file_offset, h->file_offset + h->file_size);
120 :
121 0 : if (h->flags != 0)
122 : {
123 : #define _(f,i) \
124 : if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f);
125 0 : foreach_elf_section_flag;
126 : #undef _
127 : }
128 :
129 0 : return s;
130 : }
131 :
132 : static u8 *
133 0 : format_elf_segment_type (u8 * s, va_list * args)
134 : {
135 0 : elf_segment_type_t type = va_arg (*args, elf_segment_type_t);
136 0 : char *t = 0;
137 :
138 0 : switch (type)
139 : {
140 : #define _(f,i) case ELF_SEGMENT_##f: t = #f; break;
141 0 : foreach_elf_segment_type
142 : #undef _
143 : }
144 :
145 0 : if (!t)
146 0 : s = format (s, "unknown 0x%x", type);
147 : else
148 0 : s = format (s, "%s", t);
149 0 : return s;
150 : }
151 :
152 : static u8 *
153 0 : format_elf_segment (u8 * s, va_list * args)
154 : {
155 0 : elf_segment_t *es = va_arg (*args, elf_segment_t *);
156 0 : elf64_segment_header_t *h = &es->header;
157 :
158 0 : if (!h)
159 0 : return format (s, "%=16s%=16s%=16s%=16s",
160 : "Type", "Virt. Address", "Phys. Address", "Size");
161 :
162 0 : s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx",
163 : format_elf_segment_type, h->type,
164 : h->virtual_address,
165 : h->physical_address, h->memory_size, h->file_offset);
166 :
167 0 : if (h->flags != 0)
168 : {
169 : #define _(f,i) \
170 : if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f);
171 0 : foreach_elf_segment_flag;
172 : #undef _
173 : }
174 :
175 0 : return s;
176 : }
177 :
178 : static u8 *
179 0 : format_elf_symbol_binding_and_type (u8 * s, va_list * args)
180 : {
181 0 : int bt = va_arg (*args, int);
182 : int b, t;
183 0 : char *type_string = 0;
184 0 : char *binding_string = 0;
185 :
186 0 : switch ((b = ((bt >> 4) & 0xf)))
187 : {
188 : #define _(f,n) case n: binding_string = #f; break;
189 0 : foreach_elf_symbol_binding;
190 : #undef _
191 0 : default:
192 0 : break;
193 : }
194 :
195 0 : switch ((t = ((bt >> 0) & 0xf)))
196 : {
197 : #define _(f,n) case n: type_string = #f; break;
198 0 : foreach_elf_symbol_type;
199 : #undef _
200 0 : default:
201 0 : break;
202 : }
203 :
204 0 : if (binding_string)
205 0 : s = format (s, "%s", binding_string);
206 : else
207 0 : s = format (s, "binding 0x%x", b);
208 :
209 0 : if (type_string)
210 0 : s = format (s, " %s", type_string);
211 : else
212 0 : s = format (s, " type 0x%x", t);
213 :
214 0 : return s;
215 : }
216 :
217 : static u8 *
218 0 : format_elf_symbol_visibility (u8 * s, va_list * args)
219 : {
220 0 : int visibility = va_arg (*args, int);
221 0 : char *t = 0;
222 :
223 0 : switch (visibility)
224 : {
225 : #define _(f,n) case n: t = #f; break;
226 0 : foreach_elf_symbol_visibility
227 : #undef _
228 : }
229 :
230 0 : if (t)
231 0 : return format (s, "%s", t);
232 : else
233 0 : return format (s, "unknown 0x%x", visibility);
234 : }
235 :
236 : static u8 *
237 0 : format_elf_symbol_section_name (u8 * s, va_list * args)
238 : {
239 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
240 0 : int si = va_arg (*args, int);
241 0 : char *t = 0;
242 :
243 0 : if (si < vec_len (em->sections))
244 : {
245 0 : elf_section_t *es = vec_elt_at_index (em->sections, si);
246 0 : return format (s, "%s", elf_section_name (em, es));
247 : }
248 :
249 0 : if (si >= ELF_SYMBOL_SECTION_RESERVED_LO
250 0 : && si <= ELF_SYMBOL_SECTION_RESERVED_HI)
251 : {
252 0 : switch (si)
253 : {
254 : #define _(f,n) case n: t = #f; break;
255 0 : foreach_elf_symbol_reserved_section_index
256 : #undef _
257 0 : default:
258 0 : break;
259 : }
260 0 : }
261 :
262 0 : if (t)
263 0 : return format (s, "%s", t);
264 : else
265 0 : return format (s, "unknown 0x%x", si);
266 : }
267 :
268 : u8 *
269 0 : format_elf_symbol (u8 * s, va_list * args)
270 : {
271 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
272 0 : elf_symbol_table_t *t = va_arg (*args, elf_symbol_table_t *);
273 0 : elf64_symbol_t *sym = va_arg (*args, elf64_symbol_t *);
274 :
275 0 : if (!sym)
276 0 : return format (s, "%=32s%=16s%=16s%=16s%=16s%=16s",
277 : "Symbol", "Size", "Value", "Type", "Visibility",
278 : "Section");
279 :
280 0 : s = format (s, "%-32s%16Ld%16Lx%=16U%=16U%U",
281 : elf_symbol_name (t, sym),
282 : sym->size, sym->value,
283 0 : format_elf_symbol_binding_and_type, sym->binding_and_type,
284 0 : format_elf_symbol_visibility, sym->visibility,
285 0 : format_elf_symbol_section_name, em, sym->section_index);
286 :
287 0 : return s;
288 : }
289 :
290 : static u8 *
291 0 : format_elf_relocation_type (u8 * s, va_list * args)
292 : {
293 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
294 0 : int type = va_arg (*args, int);
295 0 : char *t = 0;
296 :
297 0 : switch (em->first_header.architecture)
298 : {
299 : #define _(f,i) [i] = #f,
300 :
301 0 : case ELF_ARCH_X86_64:
302 : {
303 : static char *tab[] = {
304 : foreach_elf_x86_64_relocation_type
305 : };
306 :
307 : #undef _
308 0 : if (type < ARRAY_LEN (tab))
309 0 : t = tab[type];
310 0 : break;
311 : }
312 :
313 0 : default:
314 0 : break;
315 : }
316 :
317 0 : if (!t)
318 0 : s = format (s, "0x%02x", type);
319 : else
320 0 : s = format (s, "%s", t);
321 :
322 0 : return s;
323 : }
324 :
325 : static u8 *
326 0 : format_elf_relocation (u8 * s, va_list * args)
327 : {
328 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
329 0 : elf_relocation_with_addend_t *r =
330 : va_arg (*args, elf_relocation_with_addend_t *);
331 : elf_symbol_table_t *t;
332 : elf64_symbol_t *sym;
333 :
334 0 : if (!r)
335 0 : return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol");
336 :
337 0 : t = vec_elt_at_index (em->symbol_tables, 0);
338 0 : sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32);
339 :
340 0 : s = format (s, "%16Lx%16U",
341 : r->address,
342 0 : format_elf_relocation_type, em, r->symbol_and_type & 0xff);
343 :
344 0 : if (sym->section_index != 0)
345 : {
346 : elf_section_t *es;
347 0 : es = vec_elt_at_index (em->sections, sym->section_index);
348 0 : s = format (s, " (section %s)", elf_section_name (em, es));
349 : }
350 :
351 0 : if (sym->name != 0)
352 0 : s = format (s, " %s", elf_symbol_name (t, sym));
353 :
354 : {
355 0 : i64 a = r->addend;
356 0 : if (a != 0)
357 0 : s = format (s, " %c 0x%Lx", a > 0 ? '+' : '-', a > 0 ? a : -a);
358 : }
359 :
360 0 : return s;
361 : }
362 :
363 : static u8 *
364 0 : format_elf_dynamic_entry_type (u8 * s, va_list * args)
365 : {
366 0 : u32 type = va_arg (*args, u32);
367 0 : char *t = 0;
368 0 : switch (type)
369 : {
370 : #define _(f,n) case n: t = #f; break;
371 0 : foreach_elf_dynamic_entry_type;
372 : #undef _
373 0 : default:
374 0 : break;
375 : }
376 0 : if (t)
377 0 : return format (s, "%s", t);
378 : else
379 0 : return format (s, "unknown 0x%x", type);
380 : }
381 :
382 : static u8 *
383 0 : format_elf_dynamic_entry (u8 * s, va_list * args)
384 : {
385 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
386 0 : elf64_dynamic_entry_t *e = va_arg (*args, elf64_dynamic_entry_t *);
387 :
388 0 : if (!e)
389 0 : return format (s, "%=40s%=16s", "Type", "Data");
390 :
391 0 : s = format (s, "%=40U", format_elf_dynamic_entry_type, (u32) e->type);
392 0 : switch (e->type)
393 : {
394 0 : case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
395 : case ELF_DYNAMIC_ENTRY_RPATH:
396 : case ELF_DYNAMIC_ENTRY_RUN_PATH:
397 0 : s = format (s, "%s", em->dynamic_string_table + e->data);
398 0 : break;
399 :
400 0 : case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
401 : case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
402 : case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
403 : case ELF_DYNAMIC_ENTRY_GNU_HASH:
404 : case ELF_DYNAMIC_ENTRY_STRING_TABLE:
405 : case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
406 : case ELF_DYNAMIC_ENTRY_PLT_GOT:
407 : case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
408 : case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
409 : case ELF_DYNAMIC_ENTRY_VERSION_NEED:
410 : case ELF_DYNAMIC_ENTRY_VERSYM:
411 : {
412 : elf_section_t *es =
413 0 : elf_get_section_by_start_address_no_check (em, e->data);
414 0 : if (es)
415 0 : s = format (s, "section %s", elf_section_name (em, es));
416 : else
417 0 : s = format (s, "0x%Lx", e->data);
418 0 : break;
419 : }
420 :
421 0 : default:
422 0 : s = format (s, "0x%Lx", e->data);
423 0 : break;
424 : }
425 :
426 0 : return s;
427 : }
428 :
429 : static u8 *
430 0 : format_elf_architecture (u8 * s, va_list * args)
431 : {
432 0 : int a = va_arg (*args, int);
433 : char *t;
434 :
435 0 : switch (a)
436 : {
437 : #define _(f,n) case n: t = #f; break;
438 0 : foreach_elf_architecture;
439 : #undef _
440 0 : default:
441 0 : return format (s, "unknown 0x%x", a);
442 : }
443 :
444 0 : return format (s, "%s", t);
445 : }
446 :
447 : static u8 *
448 0 : format_elf_abi (u8 * s, va_list * args)
449 : {
450 0 : int a = va_arg (*args, int);
451 : char *t;
452 :
453 0 : switch (a)
454 : {
455 : #define _(f,n) case n: t = #f; break;
456 0 : foreach_elf_abi;
457 : #undef _
458 0 : default:
459 0 : return format (s, "unknown 0x%x", a);
460 : }
461 :
462 0 : return format (s, "%s", t);
463 : }
464 :
465 : static u8 *
466 0 : format_elf_file_class (u8 * s, va_list * args)
467 : {
468 0 : int a = va_arg (*args, int);
469 : char *t;
470 :
471 0 : switch (a)
472 : {
473 : #define _(f) case ELF_##f: t = #f; break;
474 0 : foreach_elf_file_class;
475 : #undef _
476 0 : default:
477 0 : return format (s, "unknown 0x%x", a);
478 : }
479 :
480 0 : return format (s, "%s", t);
481 : }
482 :
483 : static u8 *
484 0 : format_elf_file_type (u8 * s, va_list * args)
485 : {
486 0 : int a = va_arg (*args, int);
487 : char *t;
488 :
489 0 : if (a >= ELF_ARCH_SPECIFIC_LO && a <= ELF_ARCH_SPECIFIC_HI)
490 0 : return format (s, "arch-specific 0x%x", a - ELF_ARCH_SPECIFIC_LO);
491 :
492 0 : if (a >= ELF_OS_SPECIFIC_LO && a <= ELF_OS_SPECIFIC_HI)
493 0 : return format (s, "os-specific 0x%x", a - ELF_OS_SPECIFIC_LO);
494 :
495 0 : switch (a)
496 : {
497 : #define _(f,n) case n: t = #f; break;
498 0 : foreach_elf_file_type;
499 : #undef _
500 0 : default:
501 0 : return format (s, "unknown 0x%x", a);
502 : }
503 :
504 0 : return format (s, "%s", t);
505 : }
506 :
507 : static u8 *
508 0 : format_elf_data_encoding (u8 * s, va_list * args)
509 : {
510 0 : int a = va_arg (*args, int);
511 : char *t;
512 :
513 0 : switch (a)
514 : {
515 : #define _(f) case ELF_##f: t = #f; break;
516 0 : foreach_elf_data_encoding;
517 : #undef _
518 0 : default:
519 0 : return format (s, "unknown 0x%x", a);
520 : }
521 :
522 0 : return format (s, "%s", t);
523 : }
524 :
525 : static int
526 0 : elf_section_offset_compare (void *a1, void *a2)
527 : {
528 0 : elf_section_t *s1 = a1;
529 0 : elf_section_t *s2 = a2;
530 :
531 0 : return ((i64) s1->header.file_offset - (i64) s2->header.file_offset);
532 : }
533 :
534 : static int
535 0 : elf_segment_va_compare (void *a1, void *a2)
536 : {
537 0 : elf_segment_t *s1 = a1;
538 0 : elf_segment_t *s2 = a2;
539 :
540 0 : return ((i64) s1->header.virtual_address -
541 0 : (i64) s2->header.virtual_address);
542 : }
543 :
544 : __clib_export u8 *
545 0 : format_elf_main (u8 *s, va_list *args)
546 : {
547 0 : elf_main_t *em = va_arg (*args, elf_main_t *);
548 0 : u32 verbose = va_arg (*args, u32);
549 0 : elf64_file_header_t *fh = &em->file_header;
550 :
551 : s =
552 0 : format (s,
553 : "File header: machine: %U, file type/class %U/%U, data-encoding: %U, abi: %U version %d\n",
554 0 : format_elf_architecture, em->first_header.architecture,
555 0 : format_elf_file_type, em->first_header.file_type,
556 0 : format_elf_file_class, em->first_header.file_class,
557 0 : format_elf_data_encoding, em->first_header.data_encoding,
558 0 : format_elf_abi, em->first_header.abi,
559 0 : em->first_header.abi_version);
560 :
561 0 : s = format (s, " entry 0x%Lx, arch-flags 0x%x",
562 : em->file_header.entry_point, em->file_header.flags);
563 :
564 0 : if (em->interpreter)
565 0 : s = format (s, "\n interpreter: %s", em->interpreter);
566 :
567 : {
568 : elf_section_t *h, *copy;
569 :
570 0 : copy = 0;
571 0 : vec_foreach (h, em->sections) if (h->header.type != ~0)
572 0 : vec_add1 (copy, h[0]);
573 :
574 0 : vec_sort_with_function (copy, elf_section_offset_compare);
575 :
576 0 : s = format (s, "\nSections %d at file offset 0x%Lx-0x%Lx:\n",
577 0 : fh->section_header_count,
578 : fh->section_header_file_offset,
579 0 : fh->section_header_file_offset +
580 0 : (u64) fh->section_header_count * fh->section_header_size);
581 0 : s = format (s, "%U\n", format_elf_section, em, 0);
582 0 : vec_foreach (h, copy) s = format (s, "%U\n", format_elf_section, em, h);
583 :
584 0 : vec_free (copy);
585 : }
586 :
587 : {
588 : elf_segment_t *h, *copy;
589 :
590 0 : copy = 0;
591 0 : vec_foreach (h, em->segments)
592 0 : if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
593 0 : vec_add1 (copy, h[0]);
594 :
595 : /* Sort segments by address. */
596 0 : vec_sort_with_function (copy, elf_segment_va_compare);
597 :
598 0 : s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n",
599 0 : fh->segment_header_count,
600 : fh->segment_header_file_offset,
601 0 : (u64) fh->segment_header_file_offset +
602 0 : (u64) fh->segment_header_count *
603 0 : (u64) fh->segment_header_size);
604 :
605 0 : s = format (s, "%U\n", format_elf_segment, 0);
606 0 : vec_foreach (h, copy) s = format (s, "%U\n", format_elf_segment, h);
607 :
608 0 : vec_free (copy);
609 : }
610 :
611 0 : if ((verbose & FORMAT_ELF_MAIN_SYMBOLS) && vec_len (em->symbol_tables) > 0)
612 : {
613 : elf_symbol_table_t *t;
614 : elf64_symbol_t *sym;
615 : elf_section_t *es;
616 :
617 0 : vec_foreach (t, em->symbol_tables)
618 : {
619 0 : es = vec_elt_at_index (em->sections, t->section_index);
620 : s =
621 0 : format (s, "\nSymbols for section %s:\n",
622 : elf_section_name (em, es));
623 :
624 0 : s = format (s, "%U\n", format_elf_symbol, em, 0, 0);
625 0 : vec_foreach (sym, t->symbols)
626 0 : s = format (s, "%U\n", format_elf_symbol, em, t, sym);
627 : }
628 : }
629 :
630 0 : if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
631 0 : && vec_len (em->relocation_tables) > 0)
632 : {
633 : elf_relocation_table_t *t;
634 : elf_relocation_with_addend_t *r;
635 : elf_section_t *es;
636 :
637 0 : vec_foreach (t, em->relocation_tables)
638 : {
639 0 : es = vec_elt_at_index (em->sections, t->section_index);
640 0 : r = t->relocations;
641 0 : s = format (s, "\nRelocations for section %s:\n",
642 : elf_section_name (em, es));
643 :
644 0 : s = format (s, "%U\n", format_elf_relocation, em, 0);
645 0 : vec_foreach (r, t->relocations)
646 : {
647 0 : s = format (s, "%U\n", format_elf_relocation, em, r);
648 : }
649 : }
650 : }
651 :
652 0 : if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
653 0 : && vec_len (em->dynamic_entries) > 0)
654 : {
655 : elf64_dynamic_entry_t *es, *e;
656 0 : s = format (s, "\nDynamic linker information:\n");
657 0 : es = vec_dup (em->dynamic_entries);
658 0 : s = format (s, "%U\n", format_elf_dynamic_entry, em, 0);
659 0 : vec_foreach (e, es)
660 0 : s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
661 : }
662 :
663 0 : return s;
664 : }
665 :
666 : static void
667 108136 : elf_parse_segments (elf_main_t * em, void *data)
668 : {
669 108136 : void *d = data + em->file_header.segment_header_file_offset;
670 108136 : uword n = em->file_header.segment_header_count;
671 : uword i;
672 :
673 108136 : vec_resize (em->segments, n);
674 :
675 1301110 : for (i = 0; i < n; i++)
676 : {
677 1192970 : em->segments[i].index = i;
678 :
679 1192970 : if (em->first_header.file_class == ELF_64BIT)
680 : {
681 1192970 : elf64_segment_header_t *h = d;
682 : #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
683 1192970 : foreach_elf64_segment_header
684 : #undef _
685 1192970 : d = (h + 1);
686 : }
687 : else
688 : {
689 0 : elf32_segment_header_t *h = d;
690 : #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
691 0 : foreach_elf32_segment_header
692 : #undef _
693 0 : d = (h + 1);
694 : }
695 : }
696 108136 : }
697 :
698 : static void
699 108136 : elf_parse_sections (elf_main_t * em, void *data)
700 : {
701 108136 : elf64_file_header_t *fh = &em->file_header;
702 : elf_section_t *s;
703 108136 : void *d = data + fh->section_header_file_offset;
704 108136 : uword n = fh->section_header_count;
705 : uword i;
706 :
707 108136 : vec_resize (em->sections, n);
708 :
709 4127010 : for (i = 0; i < n; i++)
710 : {
711 4018870 : s = em->sections + i;
712 :
713 4018870 : s->index = i;
714 :
715 4018870 : if (em->first_header.file_class == ELF_64BIT)
716 : {
717 4018870 : elf64_section_header_t *h = d;
718 : #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
719 4018870 : foreach_elf64_section_header
720 : #undef _
721 4018870 : d = (h + 1);
722 : }
723 : else
724 : {
725 0 : elf32_section_header_t *h = d;
726 : #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
727 0 : foreach_elf32_section_header
728 : #undef _
729 0 : d = (h + 1);
730 : }
731 :
732 4018870 : if (s->header.type != ELF_SECTION_NO_BITS)
733 3907260 : vec_add (s->contents, data + s->header.file_offset,
734 : s->header.file_size);
735 : }
736 :
737 108136 : s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
738 :
739 : em->section_by_name
740 108136 : = hash_create_string ( /* # elts */ vec_len (em->sections),
741 : /* sizeof of value */ sizeof (uword));
742 :
743 4127010 : vec_foreach (s, em->sections)
744 : {
745 8037750 : hash_set_mem (em->section_by_name,
746 : elf_section_name (em, s), s - em->sections);
747 4018870 : hash_set (em->section_by_start_address,
748 : s->header.exec_address, s - em->sections);
749 : }
750 108136 : }
751 :
752 : static void
753 210518 : add_symbol_table (elf_main_t * em, elf_section_t * s)
754 : {
755 : elf_symbol_table_t *tab;
756 : elf32_symbol_t *sym32;
757 : elf64_symbol_t *sym64;
758 : uword i;
759 :
760 210518 : if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
761 108136 : em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
762 :
763 210518 : vec_add2 (em->symbol_tables, tab, 1);
764 :
765 210518 : tab->section_index = s->index;
766 :
767 210518 : if (em->first_header.file_class == ELF_64BIT)
768 : {
769 421036 : tab->symbols =
770 210518 : elf_get_section_contents (em, s - em->sections,
771 : sizeof (tab->symbols[0]));
772 492747000 : for (i = 0; i < vec_len (tab->symbols); i++)
773 : {
774 : #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
775 492537000 : foreach_elf64_symbol_header;
776 : #undef _
777 : }
778 : }
779 : else
780 : {
781 : sym32 =
782 0 : elf_get_section_contents (em, s - em->sections, sizeof (sym32[0]));
783 0 : vec_clone (tab->symbols, sym32);
784 0 : for (i = 0; i < vec_len (tab->symbols); i++)
785 : {
786 : #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
787 0 : foreach_elf32_symbol_header;
788 : #undef _
789 : }
790 : }
791 :
792 210518 : if (s->header.link == 0)
793 0 : return;
794 :
795 421036 : tab->string_table =
796 210518 : elf_get_section_contents (em, s->header.link,
797 : sizeof (tab->string_table[0]));
798 210518 : tab->symbol_by_name =
799 210518 : hash_create_string ( /* # elts */ vec_len (tab->symbols),
800 : /* sizeof of value */ sizeof (uword));
801 :
802 492747000 : vec_foreach (sym64, tab->symbols)
803 : {
804 492537000 : if (sym64->name != 0)
805 977622000 : hash_set_mem (tab->symbol_by_name,
806 : tab->string_table + sym64->name, sym64 - tab->symbols);
807 : }
808 : }
809 :
810 : static void
811 216272 : add_relocation_table (elf_main_t * em, elf_section_t * s)
812 : {
813 216272 : uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
814 : elf_relocation_table_t *t;
815 : uword i;
816 :
817 216272 : vec_add2 (em->relocation_tables, t, 1);
818 216272 : t->section_index = s - em->sections;
819 :
820 216272 : if (em->first_header.file_class == ELF_64BIT)
821 : {
822 : elf64_relocation_t *r, *rs;
823 :
824 432544 : rs = elf_get_section_contents (em, t->section_index,
825 216272 : sizeof (rs[0]) +
826 : has_addend * sizeof (rs->addend[0]));
827 :
828 216272 : if (em->need_byte_swap)
829 : {
830 0 : r = rs;
831 0 : for (i = 0; i < vec_len (r); i++)
832 : {
833 0 : r->address = elf_swap_u64 (em, r->address);
834 0 : r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
835 0 : if (has_addend)
836 0 : r->addend[0] = elf_swap_u64 (em, r->addend[0]);
837 0 : r = elf_relocation_next (r, s->header.type);
838 : }
839 : }
840 :
841 216272 : vec_resize (t->relocations, vec_len (rs));
842 216272 : clib_memcpy (t->relocations, rs, vec_bytes (t->relocations));
843 216272 : vec_free (rs);
844 : }
845 : else
846 : {
847 : elf_relocation_with_addend_t *r;
848 : elf32_relocation_t *r32, *r32s;
849 :
850 0 : r32s = elf_get_section_contents (em, t->section_index,
851 0 : sizeof (r32s[0]) +
852 : has_addend * sizeof (r32s->addend[0]));
853 0 : vec_resize (t->relocations, vec_len (r32s));
854 :
855 0 : r32 = r32s;
856 0 : vec_foreach (r, t->relocations)
857 : {
858 0 : r->address = elf_swap_u32 (em, r32->address);
859 0 : r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
860 0 : r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0;
861 0 : r32 = elf_relocation_next (r32, s->header.type);
862 : }
863 :
864 0 : vec_free (r32s);
865 : }
866 216272 : }
867 :
868 : void
869 108136 : elf_parse_symbols (elf_main_t * em)
870 : {
871 : elf_section_t *s;
872 :
873 : /* No need to parse symbols twice. */
874 108136 : if (em->parsed_symbols)
875 0 : return;
876 108136 : em->parsed_symbols = 1;
877 :
878 4127010 : vec_foreach (s, em->sections)
879 : {
880 4018870 : switch (s->header.type)
881 : {
882 210518 : case ELF_SECTION_SYMBOL_TABLE:
883 : case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
884 210518 : add_symbol_table (em, s);
885 210518 : break;
886 :
887 216272 : case ELF_SECTION_RELOCATION_ADD:
888 : case ELF_SECTION_RELOCATION:
889 216272 : add_relocation_table (em, s);
890 216272 : break;
891 :
892 3592080 : default:
893 3592080 : break;
894 : }
895 : }
896 : }
897 :
898 : __clib_export void
899 0 : elf_set_dynamic_entries (elf_main_t *em)
900 : {
901 : uword i;
902 :
903 : /* Start address for sections may have changed. */
904 : {
905 : elf64_dynamic_entry_t *e;
906 :
907 0 : vec_foreach (e, em->dynamic_entries)
908 : {
909 0 : switch (e->type)
910 : {
911 0 : case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
912 : case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
913 : case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
914 : case ELF_DYNAMIC_ENTRY_GNU_HASH:
915 : case ELF_DYNAMIC_ENTRY_STRING_TABLE:
916 : case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
917 : case ELF_DYNAMIC_ENTRY_PLT_GOT:
918 : case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
919 : case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
920 : case ELF_DYNAMIC_ENTRY_VERSION_NEED:
921 : case ELF_DYNAMIC_ENTRY_VERSYM:
922 : {
923 : elf_section_t *es =
924 0 : elf_get_section_by_start_address_no_check (em, e->data);
925 : /* If section is not found just leave e->data alone. */
926 0 : if (es)
927 0 : e->data = es->header.exec_address;
928 0 : break;
929 : }
930 :
931 0 : default:
932 0 : break;
933 : }
934 : }
935 : }
936 :
937 0 : if (em->first_header.file_class == ELF_64BIT)
938 : {
939 : elf64_dynamic_entry_t *e, *es;
940 :
941 0 : es = em->dynamic_entries;
942 0 : if (em->need_byte_swap)
943 : {
944 0 : es = vec_dup (es);
945 0 : vec_foreach (e, es)
946 : {
947 0 : e->type = elf_swap_u64 (em, e->type);
948 0 : e->data = elf_swap_u64 (em, e->data);
949 : }
950 : }
951 :
952 0 : elf_set_section_contents (em, em->dynamic_section_index, es,
953 0 : vec_bytes (es));
954 0 : if (es != em->dynamic_entries)
955 0 : vec_free (es);
956 : }
957 : else
958 : {
959 : elf32_dynamic_entry_t *es;
960 :
961 0 : vec_clone (es, em->dynamic_entries);
962 0 : if (em->need_byte_swap)
963 : {
964 0 : for (i = 0; i < vec_len (es); i++)
965 : {
966 0 : es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type);
967 0 : es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data);
968 : }
969 : }
970 :
971 0 : elf_set_section_contents (em, em->dynamic_section_index, es,
972 0 : vec_bytes (es));
973 0 : vec_free (es);
974 : }
975 0 : }
976 :
977 : clib_error_t *
978 108136 : elf_parse (elf_main_t * em, void *data, uword data_bytes)
979 : {
980 108136 : elf_first_header_t *h = data;
981 108136 : elf64_file_header_t *fh = &em->file_header;
982 108136 : clib_error_t *error = 0;
983 :
984 : {
985 108136 : char *save = em->file_name;
986 108136 : clib_memset (em, 0, sizeof (em[0]));
987 108136 : em->file_name = save;
988 : }
989 :
990 108136 : em->first_header = h[0];
991 108136 : em->need_byte_swap =
992 108136 : CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding ==
993 : ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
994 108136 : elf_swap_first_header (em, &em->first_header);
995 :
996 108136 : if (!(h->magic[0] == 0x7f
997 108136 : && h->magic[1] == 'E' && h->magic[2] == 'L' && h->magic[3] == 'F'))
998 0 : return clib_error_return (0, "`%s': bad magic", em->file_name);
999 :
1000 108136 : if (h->file_class == ELF_64BIT)
1001 : {
1002 108136 : elf64_file_header_t *h64 = (void *) (h + 1);
1003 : #define _(t,f) fh->f = elf_swap_##t (em, h64->f);
1004 108136 : foreach_elf64_file_header
1005 : #undef _
1006 : }
1007 : else
1008 : {
1009 0 : elf32_file_header_t *h32 = (void *) (h + 1);
1010 :
1011 : #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
1012 0 : foreach_elf32_file_header
1013 : #undef _
1014 : }
1015 :
1016 108136 : elf_parse_segments (em, data);
1017 108136 : elf_parse_sections (em, data);
1018 :
1019 : /* Figure which sections are contained in each segment. */
1020 : {
1021 : elf_segment_t *g;
1022 : elf_section_t *s;
1023 1301110 : vec_foreach (g, em->segments)
1024 : {
1025 : u64 g_lo, g_hi;
1026 : u64 s_lo, s_hi;
1027 :
1028 1192970 : if (g->header.memory_size == 0)
1029 108136 : continue;
1030 :
1031 1084840 : g_lo = g->header.virtual_address;
1032 1084840 : g_hi = g_lo + g->header.memory_size;
1033 :
1034 41471800 : vec_foreach (s, em->sections)
1035 : {
1036 40386900 : s_lo = s->header.exec_address;
1037 40386900 : s_hi = s_lo + s->header.file_size;
1038 :
1039 40386900 : if (s_lo >= g_lo && s_hi <= g_hi)
1040 : {
1041 4812710 : g->section_index_bitmap =
1042 4812710 : clib_bitmap_ori (g->section_index_bitmap, s->index);
1043 4812710 : s->segment_index_bitmap =
1044 4812710 : clib_bitmap_ori (s->segment_index_bitmap, g->index);
1045 : }
1046 : }
1047 : }
1048 : }
1049 :
1050 108136 : return error;
1051 : }
1052 :
1053 : #ifdef CLIB_UNIX
1054 :
1055 : static void
1056 50600 : add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1057 : {
1058 : uword i;
1059 :
1060 : /* Can't have more than one dynamic section. */
1061 50600 : ASSERT (em->dynamic_section_index == 0);
1062 50600 : em->dynamic_section_index = s->index;
1063 :
1064 50600 : if (em->first_header.file_class == ELF_64BIT)
1065 : {
1066 : elf64_dynamic_entry_t *e;
1067 :
1068 50600 : e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1069 50600 : if (em->need_byte_swap)
1070 0 : for (i = 0; i < vec_len (e); i++)
1071 : {
1072 0 : e[i].type = elf_swap_u64 (em, e[i].type);
1073 0 : e[i].data = elf_swap_u64 (em, e[i].data);
1074 : }
1075 :
1076 50600 : em->dynamic_entries = e;
1077 : }
1078 : else
1079 : {
1080 : elf32_dynamic_entry_t *e;
1081 :
1082 0 : e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1083 0 : vec_clone (em->dynamic_entries, e);
1084 0 : if (em->need_byte_swap)
1085 0 : for (i = 0; i < vec_len (e); i++)
1086 : {
1087 0 : em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type);
1088 0 : em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data);
1089 : }
1090 :
1091 0 : vec_free (e);
1092 : }
1093 50600 : }
1094 :
1095 : static void
1096 0 : byte_swap_verneed (elf_main_t * em, elf_dynamic_version_need_union_t * vus)
1097 : {
1098 0 : uword *entries_swapped = 0;
1099 : uword i, j;
1100 :
1101 0 : for (i = 0; i < vec_len (vus); i++)
1102 : {
1103 0 : elf_dynamic_version_need_union_t *n = vec_elt_at_index (vus, i);
1104 : elf_dynamic_version_need_union_t *a;
1105 :
1106 0 : if (clib_bitmap_get (entries_swapped, i))
1107 0 : continue;
1108 :
1109 0 : elf_swap_verneed (&n->need);
1110 0 : entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1111 :
1112 0 : if (n->need.first_aux_offset != 0)
1113 : {
1114 0 : ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1115 0 : j = i + (n->need.first_aux_offset / sizeof (n[0]));
1116 : while (1)
1117 : {
1118 0 : a = vec_elt_at_index (vus, j);
1119 0 : if (!clib_bitmap_get (entries_swapped, j))
1120 : {
1121 0 : entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1122 0 : elf_swap_verneed_aux (&a->aux);
1123 : }
1124 0 : if (a->aux.next_offset == 0)
1125 0 : break;
1126 0 : ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1127 0 : j += (a->aux.next_offset / sizeof (a->aux));
1128 : }
1129 : }
1130 : }
1131 :
1132 0 : clib_bitmap_free (entries_swapped);
1133 0 : }
1134 :
1135 : static void set_dynamic_verneed (elf_main_t * em) __attribute__ ((unused));
1136 : static void
1137 0 : set_dynamic_verneed (elf_main_t * em)
1138 : {
1139 0 : elf_dynamic_version_need_union_t *vus = em->verneed;
1140 :
1141 0 : if (em->need_byte_swap)
1142 : {
1143 0 : vus = vec_dup (vus);
1144 0 : byte_swap_verneed (em, vus);
1145 : }
1146 :
1147 0 : elf_set_section_contents (em, em->verneed_section_index, vus,
1148 0 : vec_bytes (vus));
1149 0 : if (vus != em->verneed)
1150 0 : vec_free (vus);
1151 0 : }
1152 :
1153 : static void
1154 : set_symbol_table (elf_main_t * em, u32 table_index) __attribute__ ((unused));
1155 : static void
1156 0 : set_symbol_table (elf_main_t * em, u32 table_index)
1157 : {
1158 0 : elf_symbol_table_t *tab = vec_elt_at_index (em->symbol_tables, table_index);
1159 :
1160 0 : if (em->first_header.file_class == ELF_64BIT)
1161 : {
1162 : elf64_symbol_t *s, *syms;
1163 :
1164 0 : syms = vec_dup (tab->symbols);
1165 0 : vec_foreach (s, syms)
1166 : {
1167 : #define _(t,f) s->f = elf_swap_##t (em, s->f);
1168 0 : foreach_elf64_symbol_header;
1169 : #undef _
1170 : }
1171 :
1172 0 : elf_set_section_contents (em, tab->section_index,
1173 0 : syms, vec_bytes (syms));
1174 : }
1175 : else
1176 : {
1177 : elf32_symbol_t *syms;
1178 : uword i;
1179 0 : vec_clone (syms, tab->symbols);
1180 0 : for (i = 0; i < vec_len (tab->symbols); i++)
1181 : {
1182 : #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1183 0 : foreach_elf32_symbol_header;
1184 : #undef _
1185 : }
1186 :
1187 0 : elf_set_section_contents (em, tab->section_index,
1188 0 : syms, vec_bytes (syms));
1189 : }
1190 0 : }
1191 :
1192 : static char *
1193 50600 : elf_find_interpreter (elf_main_t * em, void *data)
1194 : {
1195 : elf_segment_t *g;
1196 : elf_section_t *s;
1197 : uword *p;
1198 :
1199 607200 : vec_foreach (g, em->segments)
1200 : {
1201 556600 : if (g->header.type == ELF_SEGMENT_INTERP)
1202 0 : break;
1203 : }
1204 :
1205 50600 : if (g >= vec_end (em->segments))
1206 50600 : return 0;
1207 :
1208 0 : p = hash_get (em->section_by_start_address, g->header.virtual_address);
1209 0 : if (!p)
1210 0 : return 0;
1211 :
1212 0 : s = vec_elt_at_index (em->sections, p[0]);
1213 0 : return (char *) vec_dup (s->contents);
1214 : }
1215 :
1216 : static void *
1217 151800 : elf_get_section_contents_with_starting_address (elf_main_t * em,
1218 : uword start_address,
1219 : uword elt_size,
1220 : u32 * section_index_result)
1221 : {
1222 151800 : elf_section_t *s = 0;
1223 : clib_error_t *error;
1224 :
1225 151800 : error = elf_get_section_by_start_address (em, start_address, &s);
1226 151800 : if (error)
1227 : {
1228 0 : clib_error_report (error);
1229 0 : return 0;
1230 : }
1231 :
1232 151800 : if (section_index_result)
1233 151800 : *section_index_result = s->index;
1234 :
1235 151800 : return elf_get_section_contents (em, s->index, elt_size);
1236 : }
1237 :
1238 : static void
1239 50600 : elf_parse_dynamic (elf_main_t * em)
1240 : {
1241 : elf_section_t *s;
1242 : elf64_dynamic_entry_t *e;
1243 :
1244 1942350 : vec_foreach (s, em->sections)
1245 : {
1246 1891750 : switch (s->header.type)
1247 : {
1248 50600 : case ELF_SECTION_DYNAMIC:
1249 50600 : add_dynamic_entries (em, s);
1250 50600 : break;
1251 :
1252 1841150 : default:
1253 1841150 : break;
1254 : }
1255 : }
1256 :
1257 50600 : em->dynamic_string_table_section_index = ~0;
1258 50600 : em->dynamic_string_table = 0;
1259 :
1260 1579520 : vec_foreach (e, em->dynamic_entries)
1261 : {
1262 1528920 : switch (e->type)
1263 : {
1264 50600 : case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1265 50600 : ASSERT (vec_len (em->dynamic_string_table) == 0);
1266 : em->dynamic_string_table
1267 50600 : =
1268 50600 : elf_get_section_contents_with_starting_address (em, e->data,
1269 : sizeof (u8),
1270 : &em->
1271 : dynamic_string_table_section_index);
1272 50600 : break;
1273 :
1274 50600 : case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1275 : {
1276 50600 : elf_section_t *s = 0;
1277 : clib_error_t *error;
1278 :
1279 50600 : error = elf_get_section_by_start_address (em, e->data, &s);
1280 50600 : if (error)
1281 : {
1282 0 : clib_error_report (error);
1283 0 : return;
1284 : }
1285 :
1286 50600 : em->dynamic_symbol_table_section_index = s - em->sections;
1287 : }
1288 50600 : break;
1289 :
1290 50600 : case ELF_DYNAMIC_ENTRY_VERSYM:
1291 : em->versym
1292 50600 : =
1293 50600 : elf_get_section_contents_with_starting_address (em, e->data,
1294 : sizeof (em->versym
1295 : [0]),
1296 : &em->
1297 : versym_section_index);
1298 50600 : if (em->need_byte_swap)
1299 : {
1300 : uword i;
1301 0 : for (i = 0; i < vec_len (em->versym); i++)
1302 0 : em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1303 : }
1304 50600 : break;
1305 :
1306 50600 : case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1307 : em->verneed
1308 50600 : =
1309 50600 : elf_get_section_contents_with_starting_address (em, e->data,
1310 : sizeof (em->verneed
1311 : [0]),
1312 : &em->
1313 : verneed_section_index);
1314 50600 : if (em->need_byte_swap)
1315 0 : byte_swap_verneed (em, em->verneed);
1316 50600 : break;
1317 :
1318 1326520 : default:
1319 1326520 : break;
1320 : }
1321 : }
1322 : }
1323 :
1324 : #include <sys/types.h>
1325 : #include <sys/stat.h>
1326 : #include <fcntl.h>
1327 :
1328 : __clib_export clib_error_t *
1329 50600 : elf_read_file (elf_main_t * em, char *file_name)
1330 : {
1331 : int fd;
1332 : struct stat fd_stat;
1333 50600 : uword mmap_length = 0;
1334 50600 : void *data = 0;
1335 50600 : clib_error_t *error = 0;
1336 :
1337 50600 : elf_main_init (em);
1338 :
1339 50600 : fd = open (file_name, 0);
1340 50600 : if (fd < 0)
1341 : {
1342 0 : error = clib_error_return_unix (0, "open `%s'", file_name);
1343 0 : goto done;
1344 : }
1345 :
1346 50600 : if (fstat (fd, &fd_stat) < 0)
1347 : {
1348 0 : error = clib_error_return_unix (0, "fstat `%s'", file_name);
1349 0 : goto done;
1350 : }
1351 50600 : mmap_length = fd_stat.st_size;
1352 :
1353 50600 : data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0);
1354 50600 : if (~pointer_to_uword (data) == 0)
1355 : {
1356 0 : error = clib_error_return_unix (0, "mmap `%s'", file_name);
1357 0 : goto done;
1358 : }
1359 :
1360 50600 : clib_mem_unpoison (data, mmap_length);
1361 :
1362 50600 : em->file_name = file_name;
1363 :
1364 50600 : error = elf_parse (em, data, mmap_length);
1365 50600 : if (error)
1366 0 : goto done;
1367 :
1368 50600 : elf_parse_symbols (em);
1369 50600 : elf_parse_dynamic (em);
1370 :
1371 50600 : em->interpreter = elf_find_interpreter (em, data);
1372 :
1373 50600 : munmap (data, mmap_length);
1374 50600 : close (fd);
1375 :
1376 50600 : return /* no error */ 0;
1377 :
1378 0 : done:
1379 0 : elf_main_free (em);
1380 0 : if (fd >= 0)
1381 0 : close (fd);
1382 0 : if (data)
1383 0 : munmap (data, mmap_length);
1384 0 : return error;
1385 : }
1386 :
1387 : typedef struct
1388 : {
1389 : u8 *new_table;
1390 :
1391 : u8 *old_table;
1392 :
1393 : uword *hash;
1394 : } string_table_builder_t;
1395 :
1396 : static u32
1397 0 : string_table_add_name (string_table_builder_t * b, u8 * n)
1398 : {
1399 : uword *p, i, j, l;
1400 :
1401 0 : p = hash_get_mem (b->hash, n);
1402 0 : if (p)
1403 0 : return p[0];
1404 :
1405 0 : l = strlen ((char *) n);
1406 0 : i = vec_len (b->new_table);
1407 0 : vec_add (b->new_table, n, l + 1);
1408 :
1409 0 : for (j = 0; j <= l; j++)
1410 : {
1411 0 : if (j > 0)
1412 : {
1413 0 : p = hash_get_mem (b->hash, n + j);
1414 :
1415 : /* Sub-string already in table? */
1416 0 : if (p)
1417 0 : continue;
1418 : }
1419 :
1420 0 : hash_set_mem (b->hash, n + j, i + j);
1421 : }
1422 :
1423 0 : return i;
1424 : }
1425 :
1426 : static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1427 : __attribute__ ((unused));
1428 : static u32
1429 0 : string_table_add_name_index (string_table_builder_t * b, u32 index)
1430 : {
1431 0 : u8 *n = b->old_table + index;
1432 0 : return string_table_add_name (b, n);
1433 : }
1434 :
1435 : static void string_table_init (string_table_builder_t * b, u8 * old_table)
1436 : __attribute__ ((unused));
1437 : static void
1438 0 : string_table_init (string_table_builder_t * b, u8 * old_table)
1439 : {
1440 0 : clib_memset (b, 0, sizeof (b[0]));
1441 0 : b->old_table = old_table;
1442 0 : b->hash = hash_create_string (0, sizeof (uword));
1443 0 : }
1444 :
1445 : static u8 *string_table_done (string_table_builder_t * b)
1446 : __attribute__ ((unused));
1447 : static u8 *
1448 0 : string_table_done (string_table_builder_t * b)
1449 : {
1450 0 : hash_free (b->hash);
1451 0 : return b->new_table;
1452 : }
1453 :
1454 : static void
1455 0 : layout_sections (elf_main_t * em)
1456 : {
1457 : elf_section_t *s;
1458 0 : u32 *deferred_symbol_and_string_sections = 0;
1459 0 : u32 n_deleted_sections = 0;
1460 : /* note: rebuild is always zero. Intent lost in the sands of time */
1461 : #if 0
1462 : int rebuild = 0;
1463 :
1464 : /* Re-build section string table (sections may have been deleted). */
1465 : if (rebuild)
1466 : {
1467 : u8 *st = 0;
1468 :
1469 : vec_foreach (s, em->sections)
1470 : {
1471 : u8 *name;
1472 : if (s->header.type == ~0)
1473 : continue;
1474 : name = elf_section_name (em, s);
1475 : s->header.name = vec_len (st);
1476 : vec_add (st, name, strlen ((char *) name) + 1);
1477 : }
1478 :
1479 : s =
1480 : vec_elt_at_index (em->sections,
1481 : em->file_header.section_header_string_table_index);
1482 :
1483 : vec_free (s->contents);
1484 : s->contents = st;
1485 : }
1486 :
1487 : /* Re-build dynamic string table. */
1488 : if (rebuild && em->dynamic_string_table_section_index != ~0)
1489 : {
1490 : string_table_builder_t b;
1491 :
1492 : string_table_init (&b, em->dynamic_string_table);
1493 :
1494 : /* Add all dynamic symbols. */
1495 : {
1496 : elf_symbol_table_t *symtab;
1497 : elf64_symbol_t *sym;
1498 :
1499 : symtab =
1500 : vec_elt_at_index (em->symbol_tables,
1501 : em->dynamic_symbol_table_index);
1502 : vec_foreach (sym, symtab->symbols)
1503 : {
1504 : u8 *name = elf_symbol_name (symtab, sym);
1505 : sym->name = string_table_add_name (&b, name);
1506 : }
1507 :
1508 : set_symbol_table (em, em->dynamic_symbol_table_index);
1509 : }
1510 :
1511 : /* Add all dynamic entries. */
1512 : {
1513 : elf64_dynamic_entry_t *e;
1514 :
1515 : vec_foreach (e, em->dynamic_entries)
1516 : {
1517 : switch (e->type)
1518 : {
1519 : case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1520 : case ELF_DYNAMIC_ENTRY_RPATH:
1521 : case ELF_DYNAMIC_ENTRY_RUN_PATH:
1522 : e->data = string_table_add_name_index (&b, e->data);
1523 : break;
1524 : }
1525 : }
1526 : }
1527 :
1528 : /* Add all version needs. */
1529 : if (vec_len (em->verneed) > 0)
1530 : {
1531 : elf_dynamic_version_need_union_t *n, *a;
1532 :
1533 : n = em->verneed;
1534 : while (1)
1535 : {
1536 : n->need.file_name_offset =
1537 : string_table_add_name_index (&b, n->need.file_name_offset);
1538 :
1539 : if (n->need.first_aux_offset != 0)
1540 : {
1541 : a = n + n->need.first_aux_offset / sizeof (n[0]);
1542 : while (1)
1543 : {
1544 : a->aux.name =
1545 : string_table_add_name_index (&b, a->aux.name);
1546 : if (a->aux.next_offset == 0)
1547 : break;
1548 : a += a->aux.next_offset / sizeof (a[0]);
1549 : }
1550 : }
1551 :
1552 : if (n->need.next_offset == 0)
1553 : break;
1554 :
1555 : n += n->need.next_offset / sizeof (n[0]);
1556 : }
1557 :
1558 : set_dynamic_verneed (em);
1559 : }
1560 :
1561 : s =
1562 : vec_elt_at_index (em->sections,
1563 : em->dynamic_string_table_section_index);
1564 :
1565 : vec_free (s->contents);
1566 : s->contents = string_table_done (&b);
1567 : }
1568 : #endif /* dead code */
1569 :
1570 : /* Figure file offsets and exec addresses for sections. */
1571 : {
1572 0 : u64 exec_address = 0, file_offset = 0;
1573 : u64 file_size, align_size;
1574 :
1575 0 : vec_foreach (s, em->sections)
1576 : {
1577 : /* Ignore deleted and unused sections. */
1578 0 : switch (s->header.type)
1579 : {
1580 0 : case ~0:
1581 0 : n_deleted_sections++;
1582 0 : case ELF_SECTION_UNUSED:
1583 0 : continue;
1584 :
1585 0 : case ELF_SECTION_STRING_TABLE:
1586 : case ELF_SECTION_SYMBOL_TABLE:
1587 0 : if (!(s->index == em->dynamic_string_table_section_index
1588 0 : || s->index ==
1589 0 : em->file_header.section_header_string_table_index))
1590 : {
1591 0 : vec_add1 (deferred_symbol_and_string_sections, s->index);
1592 0 : continue;
1593 : }
1594 0 : break;
1595 :
1596 0 : default:
1597 0 : break;
1598 : }
1599 :
1600 0 : exec_address = round_pow2_u64 (exec_address, s->header.align);
1601 :
1602 : /* Put sections we added at end of file. */
1603 0 : if (s->header.file_offset == ~0)
1604 0 : s->header.file_offset = file_offset;
1605 :
1606 : /* Follow gaps in original file. */
1607 0 : if (s->header.exec_address > exec_address)
1608 : {
1609 0 : exec_address = s->header.exec_address;
1610 0 : file_offset = s->header.file_offset;
1611 : }
1612 :
1613 0 : if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1614 : {
1615 0 : s->exec_address_change = exec_address - s->header.exec_address;
1616 0 : s->header.exec_address = exec_address;
1617 : }
1618 :
1619 0 : if (s->header.type == ELF_SECTION_NO_BITS)
1620 0 : file_size = s->header.file_size;
1621 : else
1622 0 : file_size = vec_len (s->contents);
1623 :
1624 : {
1625 : u64 align;
1626 :
1627 0 : if (s + 1 >= vec_end (em->sections))
1628 0 : align = 16;
1629 0 : else if (s[1].header.type == ELF_SECTION_NO_BITS)
1630 0 : align = 8;
1631 : else
1632 0 : align = s[1].header.align;
1633 :
1634 0 : if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1635 : {
1636 0 : u64 v = round_pow2_u64 (exec_address + file_size, align);
1637 0 : align_size = v - exec_address;
1638 : }
1639 : else
1640 : {
1641 0 : u64 v = round_pow2_u64 (file_offset + file_size, align);
1642 0 : align_size = v - file_offset;
1643 : }
1644 : }
1645 :
1646 0 : s->header.file_offset = file_offset;
1647 0 : s->header.file_size = file_size;
1648 0 : s->align_size = align_size;
1649 :
1650 0 : if (s->header.type != ELF_SECTION_NO_BITS)
1651 0 : file_offset += align_size;
1652 0 : exec_address += align_size;
1653 : }
1654 :
1655 : /* Section headers go after last section but before symbol/string
1656 : tables. */
1657 : {
1658 0 : elf64_file_header_t *fh = &em->file_header;
1659 :
1660 0 : fh->section_header_file_offset = file_offset;
1661 0 : fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1662 0 : file_offset += (u64) fh->section_header_count * fh->section_header_size;
1663 : }
1664 :
1665 : {
1666 : int i;
1667 0 : for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1668 : {
1669 0 : s =
1670 0 : vec_elt_at_index (em->sections,
1671 : deferred_symbol_and_string_sections[i]);
1672 :
1673 0 : s->header.file_offset = file_offset;
1674 0 : s->header.file_size = vec_len (s->contents);
1675 :
1676 0 : align_size = round_pow2 (vec_len (s->contents), 16);
1677 0 : s->align_size = align_size;
1678 0 : file_offset += align_size;
1679 : }
1680 0 : vec_free (deferred_symbol_and_string_sections);
1681 : }
1682 : }
1683 :
1684 : /* Update dynamic entries now that sections have been assigned
1685 : possibly new addresses. */
1686 : #if 0
1687 : if (rebuild)
1688 : elf_set_dynamic_entries (em);
1689 : #endif
1690 :
1691 : /* Update segments for changed section addresses. */
1692 : {
1693 : elf_segment_t *g;
1694 : uword si;
1695 :
1696 0 : vec_foreach (g, em->segments)
1697 : {
1698 0 : u64 s_lo, s_hi, f_lo = 0;
1699 0 : u32 n_sections = 0;
1700 :
1701 0 : if (g->header.memory_size == 0)
1702 0 : continue;
1703 :
1704 0 : s_lo = s_hi = 0;
1705 : /* *INDENT-OFF* */
1706 0 : clib_bitmap_foreach (si, g->section_index_bitmap) {
1707 : u64 lo, hi;
1708 :
1709 0 : s = vec_elt_at_index (em->sections, si);
1710 0 : lo = s->header.exec_address;
1711 0 : hi = lo + s->align_size;
1712 0 : if (n_sections == 0)
1713 : {
1714 0 : s_lo = lo;
1715 0 : s_hi = hi;
1716 0 : f_lo = s->header.file_offset;
1717 0 : n_sections++;
1718 : }
1719 : else
1720 : {
1721 0 : if (lo < s_lo)
1722 : {
1723 0 : s_lo = lo;
1724 0 : f_lo = s->header.file_offset;
1725 : }
1726 0 : if (hi > s_hi)
1727 0 : s_hi = hi;
1728 : }
1729 : }
1730 : /* *INDENT-ON* */
1731 :
1732 0 : if (n_sections == 0)
1733 0 : continue;
1734 :
1735 : /* File offset zero includes ELF headers/segment headers.
1736 : Don't change that. */
1737 0 : if (g->header.file_offset == 0 && g->header.type == ELF_SEGMENT_LOAD)
1738 : {
1739 0 : s_lo = g->header.virtual_address;
1740 0 : f_lo = g->header.file_offset;
1741 : }
1742 :
1743 0 : g->header.virtual_address = s_lo;
1744 0 : g->header.physical_address = s_lo;
1745 0 : g->header.file_offset = f_lo;
1746 0 : g->header.memory_size = s_hi - s_lo;
1747 : }
1748 : }
1749 0 : }
1750 :
1751 : __clib_export clib_error_t *
1752 0 : elf_write_file (elf_main_t *em, char *file_name)
1753 : {
1754 : int fd;
1755 : FILE *f;
1756 0 : clib_error_t *error = 0;
1757 :
1758 0 : fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1759 0 : if (fd < 0)
1760 0 : return clib_error_return_unix (0, "open `%s'", file_name);
1761 :
1762 0 : f = fdopen (fd, "w");
1763 :
1764 : /* Section contents may have changed. So, we need to update
1765 : stuff to reflect this. */
1766 0 : layout_sections (em);
1767 :
1768 : /* Write first header. */
1769 : {
1770 0 : elf_first_header_t h = em->first_header;
1771 :
1772 0 : elf_swap_first_header (em, &h);
1773 0 : if (fwrite (&h, sizeof (h), 1, f) != 1)
1774 : {
1775 0 : error = clib_error_return_unix (0, "write first header");
1776 0 : goto error;
1777 : }
1778 : }
1779 :
1780 : /* Write file header. */
1781 : {
1782 0 : elf64_file_header_t h = em->file_header;
1783 :
1784 : /* Segment headers are after first header. */
1785 0 : h.segment_header_file_offset = sizeof (elf_first_header_t);
1786 0 : if (em->first_header.file_class == ELF_64BIT)
1787 0 : h.segment_header_file_offset += sizeof (elf64_file_header_t);
1788 : else
1789 0 : h.segment_header_file_offset += sizeof (elf32_file_header_t);
1790 :
1791 0 : if (em->first_header.file_class == ELF_64BIT)
1792 : {
1793 : #define _(t,field) h.field = elf_swap_##t (em, h.field);
1794 0 : foreach_elf64_file_header;
1795 : #undef _
1796 :
1797 0 : if (fwrite (&h, sizeof (h), 1, f) != 1)
1798 : {
1799 0 : error = clib_error_return_unix (0, "write file header");
1800 0 : goto error;
1801 : }
1802 : }
1803 : else
1804 : {
1805 : elf32_file_header_t h32;
1806 :
1807 : #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1808 0 : foreach_elf32_file_header;
1809 : #undef _
1810 :
1811 0 : if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1812 : {
1813 0 : error = clib_error_return_unix (0, "write file header");
1814 0 : goto error;
1815 : }
1816 : }
1817 : }
1818 :
1819 : /* Write segment headers. */
1820 : {
1821 : elf_segment_t *s;
1822 :
1823 0 : vec_foreach (s, em->segments)
1824 : {
1825 : elf64_segment_header_t h;
1826 :
1827 0 : if (s->header.type == ~0)
1828 0 : continue;
1829 :
1830 0 : h = s->header;
1831 :
1832 0 : if (em->first_header.file_class == ELF_64BIT)
1833 : {
1834 : #define _(t,field) h.field = elf_swap_##t (em, h.field);
1835 0 : foreach_elf64_segment_header;
1836 : #undef _
1837 :
1838 0 : if (fwrite (&h, sizeof (h), 1, f) != 1)
1839 : {
1840 : error =
1841 0 : clib_error_return_unix (0, "write segment header %U",
1842 : format_elf_segment, em, s);
1843 0 : goto error;
1844 : }
1845 : }
1846 : else
1847 : {
1848 : elf32_segment_header_t h32;
1849 :
1850 : #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1851 0 : foreach_elf32_segment_header;
1852 : #undef _
1853 :
1854 0 : if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1855 : {
1856 : error =
1857 0 : clib_error_return_unix (0, "write segment header %U",
1858 : format_elf_segment, em, s);
1859 0 : goto error;
1860 : }
1861 : }
1862 : }
1863 : }
1864 :
1865 : /* Write contents for all sections. */
1866 : {
1867 : elf_section_t *s;
1868 :
1869 0 : vec_foreach (s, em->sections)
1870 : {
1871 0 : if (s->header.file_size == 0)
1872 0 : continue;
1873 :
1874 0 : if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1875 : {
1876 0 : fclose (f);
1877 0 : return clib_error_return_unix (0, "fseek 0x%Lx",
1878 : s->header.file_offset);
1879 : }
1880 :
1881 0 : if (s->header.type == ELF_SECTION_NO_BITS)
1882 : /* don't write for .bss sections */ ;
1883 0 : else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1884 : {
1885 : error =
1886 0 : clib_error_return_unix (0, "write %s section contents",
1887 : elf_section_name (em, s));
1888 0 : goto error;
1889 : }
1890 : }
1891 :
1892 : /* Finally write section headers. */
1893 0 : if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1894 : {
1895 0 : fclose (f);
1896 0 : return clib_error_return_unix
1897 : (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1898 : }
1899 :
1900 0 : vec_foreach (s, em->sections)
1901 : {
1902 : elf64_section_header_t h;
1903 :
1904 0 : if (s->header.type == ~0)
1905 0 : continue;
1906 :
1907 0 : h = s->header;
1908 :
1909 0 : if (em->first_header.file_class == ELF_64BIT)
1910 : {
1911 : #define _(t,field) h.field = elf_swap_##t (em, h.field);
1912 0 : foreach_elf64_section_header;
1913 : #undef _
1914 :
1915 0 : if (fwrite (&h, sizeof (h), 1, f) != 1)
1916 : {
1917 : error =
1918 0 : clib_error_return_unix (0, "write %s section header",
1919 : elf_section_name (em, s));
1920 0 : goto error;
1921 : }
1922 : }
1923 : else
1924 : {
1925 : elf32_section_header_t h32;
1926 :
1927 : #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1928 0 : foreach_elf32_section_header;
1929 : #undef _
1930 :
1931 0 : if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1932 : {
1933 : error =
1934 0 : clib_error_return_unix (0, "write %s section header",
1935 : elf_section_name (em, s));
1936 0 : goto error;
1937 : }
1938 : }
1939 : }
1940 : }
1941 :
1942 0 : error:
1943 0 : fclose (f);
1944 0 : return error;
1945 : }
1946 :
1947 : clib_error_t *
1948 0 : elf_delete_named_section (elf_main_t * em, char *section_name)
1949 : {
1950 0 : elf_section_t *s = 0;
1951 : clib_error_t *error;
1952 :
1953 0 : error = elf_get_section_by_name (em, section_name, &s);
1954 0 : if (error)
1955 0 : return error;
1956 :
1957 0 : s->header.type = ~0;
1958 :
1959 0 : return 0;
1960 : }
1961 :
1962 : void
1963 0 : elf_create_section_with_contents (elf_main_t * em,
1964 : char *section_name,
1965 : elf64_section_header_t * header,
1966 : void *contents, uword n_content_bytes)
1967 : {
1968 : elf_section_t *s, *sts;
1969 : u8 *st, *c;
1970 : uword *p, is_new_section;
1971 :
1972 : /* See if section already exists with given name.
1973 : If so, just replace contents. */
1974 0 : is_new_section = 0;
1975 0 : if ((p = hash_get_mem (em->section_by_name, section_name)))
1976 : {
1977 0 : s = vec_elt_at_index (em->sections, p[0]);
1978 0 : vec_set_len (s->contents, 0);
1979 0 : c = s->contents;
1980 : }
1981 : else
1982 : {
1983 0 : vec_add2 (em->sections, s, 1);
1984 0 : is_new_section = 1;
1985 0 : c = 0;
1986 : }
1987 :
1988 0 : sts =
1989 0 : vec_elt_at_index (em->sections,
1990 : em->file_header.section_header_string_table_index);
1991 0 : st = sts->contents;
1992 :
1993 0 : s->header = header[0];
1994 :
1995 0 : s->header.file_offset = ~0;
1996 0 : s->header.file_size = n_content_bytes;
1997 0 : s->index = s - em->sections;
1998 :
1999 : /* Add name to string table. */
2000 0 : s->header.name = vec_len (st);
2001 0 : vec_add (st, section_name, strlen (section_name));
2002 0 : vec_add1 (st, 0);
2003 0 : sts->contents = st;
2004 :
2005 0 : vec_resize (c, n_content_bytes);
2006 0 : clib_memcpy (c, contents, n_content_bytes);
2007 0 : s->contents = c;
2008 :
2009 0 : em->file_header.section_header_count += is_new_section
2010 0 : && s->header.type != ~0;
2011 0 : }
2012 :
2013 : uword
2014 0 : elf_delete_segment_with_type (elf_main_t * em,
2015 : elf_segment_type_t segment_type)
2016 : {
2017 0 : uword n_deleted = 0;
2018 : elf_segment_t *s;
2019 :
2020 0 : vec_foreach (s, em->segments) if (s->header.type == segment_type)
2021 : {
2022 0 : s->header.type = ~0;
2023 0 : n_deleted += 1;
2024 : }
2025 :
2026 0 : ASSERT (em->file_header.segment_header_count >= n_deleted);
2027 0 : em->file_header.segment_header_count -= n_deleted;
2028 :
2029 0 : return n_deleted;
2030 : }
2031 :
2032 : #endif /* CLIB_UNIX */
2033 :
2034 : /*
2035 : * fd.io coding-style-patch-verification: ON
2036 : *
2037 : * Local Variables:
2038 : * eval: (c-set-style "gnu")
2039 : * End:
2040 : */
|