blob: 7a74fad4c4feb1f6e73a6411758c0c8ae20462a9 [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
Damjan Marion4a251d02021-05-06 17:28:12 +020068__clib_export clib_error_t *
69elf_get_section_by_start_address (elf_main_t *em, uword start_address,
70 elf_section_t **result)
Damjan Marion7cd468a2016-12-19 23:05:39 +010071{
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
Damjan Marion4a251d02021-05-06 17:28:12 +0200544__clib_export u8 *
545format_elf_main (u8 *s, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100546{
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
Damjan Marion4a251d02021-05-06 17:28:12 +0200898__clib_export void
899elf_set_dynamic_entries (elf_main_t *em)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100900{
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;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001458 u32 *deferred_symbol_and_string_sections = 0;
1459 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 u64 exec_address = 0, file_offset = 0;
1573 u64 file_size, align_size;
1574
1575 vec_foreach (s, em->sections)
1576 {
1577 /* Ignore deleted and unused sections. */
1578 switch (s->header.type)
1579 {
1580 case ~0:
1581 n_deleted_sections++;
1582 case ELF_SECTION_UNUSED:
1583 continue;
1584
1585 case ELF_SECTION_STRING_TABLE:
1586 case ELF_SECTION_SYMBOL_TABLE:
1587 if (!(s->index == em->dynamic_string_table_section_index
1588 || s->index ==
1589 em->file_header.section_header_string_table_index))
1590 {
1591 vec_add1 (deferred_symbol_and_string_sections, s->index);
1592 continue;
1593 }
1594 break;
1595
1596 default:
1597 break;
1598 }
1599
1600 exec_address = round_pow2_u64 (exec_address, s->header.align);
1601
1602 /* Put sections we added at end of file. */
1603 if (s->header.file_offset == ~0)
1604 s->header.file_offset = file_offset;
1605
1606 /* Follow gaps in original file. */
1607 if (s->header.exec_address > exec_address)
1608 {
1609 exec_address = s->header.exec_address;
1610 file_offset = s->header.file_offset;
1611 }
1612
1613 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1614 {
1615 s->exec_address_change = exec_address - s->header.exec_address;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001616 s->header.exec_address = exec_address;
1617 }
1618
1619 if (s->header.type == ELF_SECTION_NO_BITS)
1620 file_size = s->header.file_size;
1621 else
1622 file_size = vec_len (s->contents);
1623
1624 {
1625 u64 align;
1626
1627 if (s + 1 >= vec_end (em->sections))
1628 align = 16;
1629 else if (s[1].header.type == ELF_SECTION_NO_BITS)
1630 align = 8;
1631 else
1632 align = s[1].header.align;
1633
1634 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1635 {
1636 u64 v = round_pow2_u64 (exec_address + file_size, align);
1637 align_size = v - exec_address;
1638 }
1639 else
1640 {
1641 u64 v = round_pow2_u64 (file_offset + file_size, align);
1642 align_size = v - file_offset;
1643 }
1644 }
1645
1646 s->header.file_offset = file_offset;
1647 s->header.file_size = file_size;
1648 s->align_size = align_size;
1649
1650 if (s->header.type != ELF_SECTION_NO_BITS)
1651 file_offset += align_size;
1652 exec_address += align_size;
1653 }
1654
1655 /* Section headers go after last section but before symbol/string
1656 tables. */
1657 {
1658 elf64_file_header_t *fh = &em->file_header;
1659
1660 fh->section_header_file_offset = file_offset;
1661 fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1662 file_offset += (u64) fh->section_header_count * fh->section_header_size;
1663 }
1664
1665 {
1666 int i;
1667 for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1668 {
1669 s =
1670 vec_elt_at_index (em->sections,
1671 deferred_symbol_and_string_sections[i]);
1672
1673 s->header.file_offset = file_offset;
1674 s->header.file_size = vec_len (s->contents);
1675
1676 align_size = round_pow2 (vec_len (s->contents), 16);
1677 s->align_size = align_size;
1678 file_offset += align_size;
1679 }
1680 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 vec_foreach (g, em->segments)
1697 {
1698 u64 s_lo, s_hi, f_lo = 0;
1699 u32 n_sections = 0;
1700
1701 if (g->header.memory_size == 0)
1702 continue;
1703
1704 s_lo = s_hi = 0;
1705 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +01001706 clib_bitmap_foreach (si, g->section_index_bitmap) {
Damjan Marion7cd468a2016-12-19 23:05:39 +01001707 u64 lo, hi;
1708
1709 s = vec_elt_at_index (em->sections, si);
1710 lo = s->header.exec_address;
1711 hi = lo + s->align_size;
1712 if (n_sections == 0)
1713 {
1714 s_lo = lo;
1715 s_hi = hi;
1716 f_lo = s->header.file_offset;
1717 n_sections++;
1718 }
1719 else
1720 {
1721 if (lo < s_lo)
1722 {
1723 s_lo = lo;
1724 f_lo = s->header.file_offset;
1725 }
1726 if (hi > s_hi)
1727 s_hi = hi;
1728 }
Damjan Marionf0ca1e82020-12-13 23:26:56 +01001729 }
Damjan Marion7cd468a2016-12-19 23:05:39 +01001730 /* *INDENT-ON* */
1731
1732 if (n_sections == 0)
1733 continue;
1734
1735 /* File offset zero includes ELF headers/segment headers.
1736 Don't change that. */
1737 if (g->header.file_offset == 0 && g->header.type == ELF_SEGMENT_LOAD)
1738 {
1739 s_lo = g->header.virtual_address;
1740 f_lo = g->header.file_offset;
1741 }
1742
1743 g->header.virtual_address = s_lo;
1744 g->header.physical_address = s_lo;
1745 g->header.file_offset = f_lo;
1746 g->header.memory_size = s_hi - s_lo;
1747 }
1748 }
1749}
1750
Damjan Marion4a251d02021-05-06 17:28:12 +02001751__clib_export clib_error_t *
1752elf_write_file (elf_main_t *em, char *file_name)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001753{
1754 int fd;
1755 FILE *f;
1756 clib_error_t *error = 0;
1757
1758 fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1759 if (fd < 0)
1760 return clib_error_return_unix (0, "open `%s'", file_name);
1761
1762 f = fdopen (fd, "w");
1763
1764 /* Section contents may have changed. So, we need to update
1765 stuff to reflect this. */
1766 layout_sections (em);
1767
1768 /* Write first header. */
1769 {
1770 elf_first_header_t h = em->first_header;
1771
1772 elf_swap_first_header (em, &h);
1773 if (fwrite (&h, sizeof (h), 1, f) != 1)
1774 {
1775 error = clib_error_return_unix (0, "write first header");
1776 goto error;
1777 }
1778 }
1779
1780 /* Write file header. */
1781 {
1782 elf64_file_header_t h = em->file_header;
1783
1784 /* Segment headers are after first header. */
1785 h.segment_header_file_offset = sizeof (elf_first_header_t);
1786 if (em->first_header.file_class == ELF_64BIT)
1787 h.segment_header_file_offset += sizeof (elf64_file_header_t);
1788 else
1789 h.segment_header_file_offset += sizeof (elf32_file_header_t);
1790
1791 if (em->first_header.file_class == ELF_64BIT)
1792 {
1793#define _(t,field) h.field = elf_swap_##t (em, h.field);
1794 foreach_elf64_file_header;
1795#undef _
1796
1797 if (fwrite (&h, sizeof (h), 1, f) != 1)
1798 {
1799 error = clib_error_return_unix (0, "write file header");
1800 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 foreach_elf32_file_header;
1809#undef _
1810
1811 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1812 {
1813 error = clib_error_return_unix (0, "write file header");
1814 goto error;
1815 }
1816 }
1817 }
1818
1819 /* Write segment headers. */
1820 {
1821 elf_segment_t *s;
1822
1823 vec_foreach (s, em->segments)
1824 {
1825 elf64_segment_header_t h;
1826
1827 if (s->header.type == ~0)
1828 continue;
1829
1830 h = s->header;
1831
1832 if (em->first_header.file_class == ELF_64BIT)
1833 {
1834#define _(t,field) h.field = elf_swap_##t (em, h.field);
1835 foreach_elf64_segment_header;
1836#undef _
1837
1838 if (fwrite (&h, sizeof (h), 1, f) != 1)
1839 {
1840 error =
1841 clib_error_return_unix (0, "write segment header %U",
1842 format_elf_segment, em, s);
1843 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 foreach_elf32_segment_header;
1852#undef _
1853
1854 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1855 {
1856 error =
1857 clib_error_return_unix (0, "write segment header %U",
1858 format_elf_segment, em, s);
1859 goto error;
1860 }
1861 }
1862 }
1863 }
1864
1865 /* Write contents for all sections. */
1866 {
1867 elf_section_t *s;
1868
1869 vec_foreach (s, em->sections)
1870 {
1871 if (s->header.file_size == 0)
1872 continue;
1873
1874 if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1875 {
1876 fclose (f);
1877 return clib_error_return_unix (0, "fseek 0x%Lx",
1878 s->header.file_offset);
1879 }
1880
1881 if (s->header.type == ELF_SECTION_NO_BITS)
1882 /* don't write for .bss sections */ ;
1883 else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1884 {
1885 error =
1886 clib_error_return_unix (0, "write %s section contents",
1887 elf_section_name (em, s));
1888 goto error;
1889 }
1890 }
1891
1892 /* Finally write section headers. */
1893 if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1894 {
1895 fclose (f);
1896 return clib_error_return_unix
1897 (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1898 }
1899
1900 vec_foreach (s, em->sections)
1901 {
1902 elf64_section_header_t h;
1903
1904 if (s->header.type == ~0)
1905 continue;
1906
1907 h = s->header;
1908
1909 if (em->first_header.file_class == ELF_64BIT)
1910 {
1911#define _(t,field) h.field = elf_swap_##t (em, h.field);
1912 foreach_elf64_section_header;
1913#undef _
1914
1915 if (fwrite (&h, sizeof (h), 1, f) != 1)
1916 {
1917 error =
1918 clib_error_return_unix (0, "write %s section header",
1919 elf_section_name (em, s));
1920 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 foreach_elf32_section_header;
1929#undef _
1930
1931 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1932 {
1933 error =
1934 clib_error_return_unix (0, "write %s section header",
1935 elf_section_name (em, s));
1936 goto error;
1937 }
1938 }
1939 }
1940 }
1941
1942error:
1943 fclose (f);
1944 return error;
1945}
1946
1947clib_error_t *
1948elf_delete_named_section (elf_main_t * em, char *section_name)
1949{
1950 elf_section_t *s = 0;
1951 clib_error_t *error;
1952
1953 error = elf_get_section_by_name (em, section_name, &s);
1954 if (error)
1955 return error;
1956
1957 s->header.type = ~0;
1958
1959 return 0;
1960}
1961
1962void
1963elf_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 is_new_section = 0;
1975 if ((p = hash_get_mem (em->section_by_name, section_name)))
1976 {
1977 s = vec_elt_at_index (em->sections, p[0]);
1978 _vec_len (s->contents) = 0;
1979 c = s->contents;
1980 }
1981 else
1982 {
1983 vec_add2 (em->sections, s, 1);
1984 is_new_section = 1;
1985 c = 0;
1986 }
1987
1988 sts =
1989 vec_elt_at_index (em->sections,
1990 em->file_header.section_header_string_table_index);
1991 st = sts->contents;
1992
1993 s->header = header[0];
1994
1995 s->header.file_offset = ~0;
1996 s->header.file_size = n_content_bytes;
1997 s->index = s - em->sections;
1998
1999 /* Add name to string table. */
2000 s->header.name = vec_len (st);
2001 vec_add (st, section_name, strlen (section_name));
2002 vec_add1 (st, 0);
2003 sts->contents = st;
2004
2005 vec_resize (c, n_content_bytes);
2006 clib_memcpy (c, contents, n_content_bytes);
2007 s->contents = c;
2008
2009 em->file_header.section_header_count += is_new_section
2010 && s->header.type != ~0;
2011}
2012
2013uword
2014elf_delete_segment_with_type (elf_main_t * em,
2015 elf_segment_type_t segment_type)
2016{
2017 uword n_deleted = 0;
2018 elf_segment_t *s;
2019
2020 vec_foreach (s, em->segments) if (s->header.type == segment_type)
2021 {
2022 s->header.type = ~0;
2023 n_deleted += 1;
2024 }
2025
2026 ASSERT (em->file_header.segment_header_count >= n_deleted);
2027 em->file_header.segment_header_count -= n_deleted;
2028
2029 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 */