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