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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
23 elf_swap_first_header (elf_main_t * em, elf_first_header_t * h)
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);
31 elf_swap_verneed (elf_dynamic_version_need_t * n)
33 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
34 foreach_elf_dynamic_version_need_field
39 elf_swap_verneed_aux (elf_dynamic_version_need_aux_t * n)
41 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
42 foreach_elf_dynamic_version_need_aux_field
46 __clib_export clib_error_t *
47 elf_get_section_by_name (elf_main_t * em, char *section_name,
48 elf_section_t ** result)
52 p = hash_get_mem (em->section_by_name, section_name);
54 return clib_error_return (0, "no such section `%s'", section_name);
56 *result = vec_elt_at_index (em->sections, p[0]);
61 elf_get_section_by_start_address_no_check (elf_main_t * em,
64 uword *p = hash_get (em->section_by_start_address, start_address);
65 return p ? vec_elt_at_index (em->sections, p[0]) : 0;
68 __clib_export clib_error_t *
69 elf_get_section_by_start_address (elf_main_t *em, uword start_address,
70 elf_section_t **result)
73 elf_get_section_by_start_address_no_check (em, start_address);
75 return clib_error_return (0, "no section with address 0x%wx",
82 format_elf_section_type (u8 * s, va_list * args)
84 elf_section_type_t type = va_arg (*args, elf_section_type_t);
89 #define _(f,i) case ELF_SECTION_##f: t = #f; break;
90 foreach_elf_section_type
95 s = format (s, "unknown 0x%x", type);
97 s = format (s, "%s", t);
102 format_elf_section (u8 * s, va_list * args)
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;
109 return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s",
110 "Name", "Index", "Type", "Size", "Align", "Address",
113 s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx",
114 elf_section_name (em, es),
116 format_elf_section_type, h->type,
119 h->exec_address, h->file_offset, h->file_offset + h->file_size);
124 if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f);
125 foreach_elf_section_flag;
133 format_elf_segment_type (u8 * s, va_list * args)
135 elf_segment_type_t type = va_arg (*args, elf_segment_type_t);
140 #define _(f,i) case ELF_SEGMENT_##f: t = #f; break;
141 foreach_elf_segment_type
146 s = format (s, "unknown 0x%x", type);
148 s = format (s, "%s", t);
153 format_elf_segment (u8 * s, va_list * args)
155 elf_segment_t *es = va_arg (*args, elf_segment_t *);
156 elf64_segment_header_t *h = &es->header;
159 return format (s, "%=16s%=16s%=16s%=16s",
160 "Type", "Virt. Address", "Phys. Address", "Size");
162 s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx",
163 format_elf_segment_type, h->type,
165 h->physical_address, h->memory_size, h->file_offset);
170 if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f);
171 foreach_elf_segment_flag;
179 format_elf_symbol_binding_and_type (u8 * s, va_list * args)
181 int bt = va_arg (*args, int);
183 char *type_string = 0;
184 char *binding_string = 0;
186 switch ((b = ((bt >> 4) & 0xf)))
188 #define _(f,n) case n: binding_string = #f; break;
189 foreach_elf_symbol_binding;
195 switch ((t = ((bt >> 0) & 0xf)))
197 #define _(f,n) case n: type_string = #f; break;
198 foreach_elf_symbol_type;
205 s = format (s, "%s", binding_string);
207 s = format (s, "binding 0x%x", b);
210 s = format (s, " %s", type_string);
212 s = format (s, " type 0x%x", t);
218 format_elf_symbol_visibility (u8 * s, va_list * args)
220 int visibility = va_arg (*args, int);
225 #define _(f,n) case n: t = #f; break;
226 foreach_elf_symbol_visibility
231 return format (s, "%s", t);
233 return format (s, "unknown 0x%x", visibility);
237 format_elf_symbol_section_name (u8 * s, va_list * args)
239 elf_main_t *em = va_arg (*args, elf_main_t *);
240 int si = va_arg (*args, int);
243 if (si < vec_len (em->sections))
245 elf_section_t *es = vec_elt_at_index (em->sections, si);
246 return format (s, "%s", elf_section_name (em, es));
249 if (si >= ELF_SYMBOL_SECTION_RESERVED_LO
250 && si <= ELF_SYMBOL_SECTION_RESERVED_HI)
254 #define _(f,n) case n: t = #f; break;
255 foreach_elf_symbol_reserved_section_index
263 return format (s, "%s", t);
265 return format (s, "unknown 0x%x", si);
269 format_elf_symbol (u8 * s, va_list * args)
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 *);
276 return format (s, "%=32s%=16s%=16s%=16s%=16s%=16s",
277 "Symbol", "Size", "Value", "Type", "Visibility",
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);
291 format_elf_relocation_type (u8 * s, va_list * args)
293 elf_main_t *em = va_arg (*args, elf_main_t *);
294 int type = va_arg (*args, int);
297 switch (em->first_header.architecture)
299 #define _(f,i) [i] = #f,
301 case ELF_ARCH_X86_64:
303 static char *tab[] = {
304 foreach_elf_x86_64_relocation_type
308 if (type < ARRAY_LEN (tab))
318 s = format (s, "0x%02x", type);
320 s = format (s, "%s", t);
326 format_elf_relocation (u8 * s, va_list * args)
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;
335 return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol");
337 t = vec_elt_at_index (em->symbol_tables, 0);
338 sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32);
340 s = format (s, "%16Lx%16U",
342 format_elf_relocation_type, em, r->symbol_and_type & 0xff);
344 if (sym->section_index != 0)
347 es = vec_elt_at_index (em->sections, sym->section_index);
348 s = format (s, " (section %s)", elf_section_name (em, es));
352 s = format (s, " %s", elf_symbol_name (t, sym));
357 s = format (s, " %c 0x%Lx", a > 0 ? '+' : '-', a > 0 ? a : -a);
364 format_elf_dynamic_entry_type (u8 * s, va_list * args)
366 u32 type = va_arg (*args, u32);
370 #define _(f,n) case n: t = #f; break;
371 foreach_elf_dynamic_entry_type;
377 return format (s, "%s", t);
379 return format (s, "unknown 0x%x", type);
383 format_elf_dynamic_entry (u8 * s, va_list * args)
385 elf_main_t *em = va_arg (*args, elf_main_t *);
386 elf64_dynamic_entry_t *e = va_arg (*args, elf64_dynamic_entry_t *);
389 return format (s, "%=40s%=16s", "Type", "Data");
391 s = format (s, "%=40U", format_elf_dynamic_entry_type, (u32) e->type);
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);
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:
413 elf_get_section_by_start_address_no_check (em, e->data);
415 s = format (s, "section %s", elf_section_name (em, es));
417 s = format (s, "0x%Lx", e->data);
422 s = format (s, "0x%Lx", e->data);
430 format_elf_architecture (u8 * s, va_list * args)
432 int a = va_arg (*args, int);
437 #define _(f,n) case n: t = #f; break;
438 foreach_elf_architecture;
441 return format (s, "unknown 0x%x", a);
444 return format (s, "%s", t);
448 format_elf_abi (u8 * s, va_list * args)
450 int a = va_arg (*args, int);
455 #define _(f,n) case n: t = #f; break;
459 return format (s, "unknown 0x%x", a);
462 return format (s, "%s", t);
466 format_elf_file_class (u8 * s, va_list * args)
468 int a = va_arg (*args, int);
473 #define _(f) case ELF_##f: t = #f; break;
474 foreach_elf_file_class;
477 return format (s, "unknown 0x%x", a);
480 return format (s, "%s", t);
484 format_elf_file_type (u8 * s, va_list * args)
486 int a = va_arg (*args, int);
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);
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);
497 #define _(f,n) case n: t = #f; break;
498 foreach_elf_file_type;
501 return format (s, "unknown 0x%x", a);
504 return format (s, "%s", t);
508 format_elf_data_encoding (u8 * s, va_list * args)
510 int a = va_arg (*args, int);
515 #define _(f) case ELF_##f: t = #f; break;
516 foreach_elf_data_encoding;
519 return format (s, "unknown 0x%x", a);
522 return format (s, "%s", t);
526 elf_section_offset_compare (void *a1, void *a2)
528 elf_section_t *s1 = a1;
529 elf_section_t *s2 = a2;
531 return ((i64) s1->header.file_offset - (i64) s2->header.file_offset);
535 elf_segment_va_compare (void *a1, void *a2)
537 elf_segment_t *s1 = a1;
538 elf_segment_t *s2 = a2;
540 return ((i64) s1->header.virtual_address -
541 (i64) s2->header.virtual_address);
545 format_elf_main (u8 *s, va_list *args)
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;
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);
561 s = format (s, " entry 0x%Lx, arch-flags 0x%x",
562 em->file_header.entry_point, em->file_header.flags);
565 s = format (s, "\n interpreter: %s", em->interpreter);
568 elf_section_t *h, *copy;
571 vec_foreach (h, em->sections) if (h->header.type != ~0)
572 vec_add1 (copy, h[0]);
574 vec_sort_with_function (copy, elf_section_offset_compare);
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);
588 elf_segment_t *h, *copy;
591 vec_foreach (h, em->segments)
592 if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
593 vec_add1 (copy, h[0]);
595 /* Sort segments by address. */
596 vec_sort_with_function (copy, elf_segment_va_compare);
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);
605 s = format (s, "%U\n", format_elf_segment, 0);
606 vec_foreach (h, copy) s = format (s, "%U\n", format_elf_segment, h);
611 if ((verbose & FORMAT_ELF_MAIN_SYMBOLS) && vec_len (em->symbol_tables) > 0)
613 elf_symbol_table_t *t;
617 vec_foreach (t, em->symbol_tables)
619 es = vec_elt_at_index (em->sections, t->section_index);
621 format (s, "\nSymbols for section %s:\n",
622 elf_section_name (em, es));
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);
630 if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
631 && vec_len (em->relocation_tables) > 0)
633 elf_relocation_table_t *t;
634 elf_relocation_with_addend_t *r;
637 vec_foreach (t, em->relocation_tables)
639 es = vec_elt_at_index (em->sections, t->section_index);
641 s = format (s, "\nRelocations for section %s:\n",
642 elf_section_name (em, es));
644 s = format (s, "%U\n", format_elf_relocation, em, 0);
645 vec_foreach (r, t->relocations)
647 s = format (s, "%U\n", format_elf_relocation, em, r);
652 if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
653 && vec_len (em->dynamic_entries) > 0)
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);
660 s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
667 elf_parse_segments (elf_main_t * em, void *data)
669 void *d = data + em->file_header.segment_header_file_offset;
670 uword n = em->file_header.segment_header_count;
673 vec_resize (em->segments, n);
675 for (i = 0; i < n; i++)
677 em->segments[i].index = i;
679 if (em->first_header.file_class == ELF_64BIT)
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
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
699 elf_parse_sections (elf_main_t * em, void *data)
701 elf64_file_header_t *fh = &em->file_header;
703 void *d = data + fh->section_header_file_offset;
704 uword n = fh->section_header_count;
707 vec_resize (em->sections, n);
709 for (i = 0; i < n; i++)
711 s = em->sections + i;
715 if (em->first_header.file_class == ELF_64BIT)
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
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
732 if (s->header.type != ELF_SECTION_NO_BITS)
733 vec_add (s->contents, data + s->header.file_offset,
734 s->header.file_size);
737 s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
740 = hash_create_string ( /* # elts */ vec_len (em->sections),
741 /* sizeof of value */ sizeof (uword));
743 vec_foreach (s, em->sections)
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);
753 add_symbol_table (elf_main_t * em, elf_section_t * s)
755 elf_symbol_table_t *tab;
756 elf32_symbol_t *sym32;
757 elf64_symbol_t *sym64;
760 if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
761 em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
763 vec_add2 (em->symbol_tables, tab, 1);
765 tab->section_index = s->index;
767 if (em->first_header.file_class == ELF_64BIT)
770 elf_get_section_contents (em, s - em->sections,
771 sizeof (tab->symbols[0]));
772 for (i = 0; i < vec_len (tab->symbols); i++)
774 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
775 foreach_elf64_symbol_header;
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++)
786 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
787 foreach_elf32_symbol_header;
792 if (s->header.link == 0)
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));
802 vec_foreach (sym64, tab->symbols)
804 if (sym64->name != 0)
805 hash_set_mem (tab->symbol_by_name,
806 tab->string_table + sym64->name, sym64 - tab->symbols);
811 add_relocation_table (elf_main_t * em, elf_section_t * s)
813 uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
814 elf_relocation_table_t *t;
817 vec_add2 (em->relocation_tables, t, 1);
818 t->section_index = s - em->sections;
820 if (em->first_header.file_class == ELF_64BIT)
822 elf64_relocation_t *r, *rs;
824 rs = elf_get_section_contents (em, t->section_index,
826 has_addend * sizeof (rs->addend[0]));
828 if (em->need_byte_swap)
831 for (i = 0; i < vec_len (r); i++)
833 r->address = elf_swap_u64 (em, r->address);
834 r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
836 r->addend[0] = elf_swap_u64 (em, r->addend[0]);
837 r = elf_relocation_next (r, s->header.type);
841 vec_resize (t->relocations, vec_len (rs));
842 clib_memcpy (t->relocations, rs, vec_bytes (t->relocations));
847 elf_relocation_with_addend_t *r;
848 elf32_relocation_t *r32, *r32s;
850 r32s = elf_get_section_contents (em, t->section_index,
852 has_addend * sizeof (r32s->addend[0]));
853 vec_resize (t->relocations, vec_len (r32s));
856 vec_foreach (r, t->relocations)
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);
869 elf_parse_symbols (elf_main_t * em)
873 /* No need to parse symbols twice. */
874 if (em->parsed_symbols)
876 em->parsed_symbols = 1;
878 vec_foreach (s, em->sections)
880 switch (s->header.type)
882 case ELF_SECTION_SYMBOL_TABLE:
883 case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
884 add_symbol_table (em, s);
887 case ELF_SECTION_RELOCATION_ADD:
888 case ELF_SECTION_RELOCATION:
889 add_relocation_table (em, s);
899 elf_set_dynamic_entries (elf_main_t *em)
903 /* Start address for sections may have changed. */
905 elf64_dynamic_entry_t *e;
907 vec_foreach (e, em->dynamic_entries)
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:
924 elf_get_section_by_start_address_no_check (em, e->data);
925 /* If section is not found just leave e->data alone. */
927 e->data = es->header.exec_address;
937 if (em->first_header.file_class == ELF_64BIT)
939 elf64_dynamic_entry_t *e, *es;
941 es = em->dynamic_entries;
942 if (em->need_byte_swap)
947 e->type = elf_swap_u64 (em, e->type);
948 e->data = elf_swap_u64 (em, e->data);
952 elf_set_section_contents (em, em->dynamic_section_index, es,
954 if (es != em->dynamic_entries)
959 elf32_dynamic_entry_t *es;
961 vec_clone (es, em->dynamic_entries);
962 if (em->need_byte_swap)
964 for (i = 0; i < vec_len (es); i++)
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);
971 elf_set_section_contents (em, em->dynamic_section_index, es,
978 elf_parse (elf_main_t * em, void *data, uword data_bytes)
980 elf_first_header_t *h = data;
981 elf64_file_header_t *fh = &em->file_header;
982 clib_error_t *error = 0;
985 char *save = em->file_name;
986 clib_memset (em, 0, sizeof (em[0]));
987 em->file_name = save;
990 em->first_header = h[0];
992 CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding ==
993 ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
994 elf_swap_first_header (em, &em->first_header);
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);
1000 if (h->file_class == ELF_64BIT)
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
1009 elf32_file_header_t *h32 = (void *) (h + 1);
1011 #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
1012 foreach_elf32_file_header
1016 elf_parse_segments (em, data);
1017 elf_parse_sections (em, data);
1019 /* Figure which sections are contained in each segment. */
1023 vec_foreach (g, em->segments)
1028 if (g->header.memory_size == 0)
1031 g_lo = g->header.virtual_address;
1032 g_hi = g_lo + g->header.memory_size;
1034 vec_foreach (s, em->sections)
1036 s_lo = s->header.exec_address;
1037 s_hi = s_lo + s->header.file_size;
1039 if (s_lo >= g_lo && s_hi <= g_hi)
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);
1056 add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1060 /* Can't have more than one dynamic section. */
1061 ASSERT (em->dynamic_section_index == 0);
1062 em->dynamic_section_index = s->index;
1064 if (em->first_header.file_class == ELF_64BIT)
1066 elf64_dynamic_entry_t *e;
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++)
1072 e[i].type = elf_swap_u64 (em, e[i].type);
1073 e[i].data = elf_swap_u64 (em, e[i].data);
1076 em->dynamic_entries = e;
1080 elf32_dynamic_entry_t *e;
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++)
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);
1096 byte_swap_verneed (elf_main_t * em, elf_dynamic_version_need_union_t * vus)
1098 uword *entries_swapped = 0;
1101 for (i = 0; i < vec_len (vus); i++)
1103 elf_dynamic_version_need_union_t *n = vec_elt_at_index (vus, i);
1104 elf_dynamic_version_need_union_t *a;
1106 if (clib_bitmap_get (entries_swapped, i))
1109 elf_swap_verneed (&n->need);
1110 entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1112 if (n->need.first_aux_offset != 0)
1114 ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1115 j = i + (n->need.first_aux_offset / sizeof (n[0]));
1118 a = vec_elt_at_index (vus, j);
1119 if (!clib_bitmap_get (entries_swapped, j))
1121 entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1122 elf_swap_verneed_aux (&a->aux);
1124 if (a->aux.next_offset == 0)
1126 ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1127 j += (a->aux.next_offset / sizeof (a->aux));
1132 clib_bitmap_free (entries_swapped);
1135 static void set_dynamic_verneed (elf_main_t * em) __attribute__ ((unused));
1137 set_dynamic_verneed (elf_main_t * em)
1139 elf_dynamic_version_need_union_t *vus = em->verneed;
1141 if (em->need_byte_swap)
1143 vus = vec_dup (vus);
1144 byte_swap_verneed (em, vus);
1147 elf_set_section_contents (em, em->verneed_section_index, vus,
1149 if (vus != em->verneed)
1154 set_symbol_table (elf_main_t * em, u32 table_index) __attribute__ ((unused));
1156 set_symbol_table (elf_main_t * em, u32 table_index)
1158 elf_symbol_table_t *tab = vec_elt_at_index (em->symbol_tables, table_index);
1160 if (em->first_header.file_class == ELF_64BIT)
1162 elf64_symbol_t *s, *syms;
1164 syms = vec_dup (tab->symbols);
1165 vec_foreach (s, syms)
1167 #define _(t,f) s->f = elf_swap_##t (em, s->f);
1168 foreach_elf64_symbol_header;
1172 elf_set_section_contents (em, tab->section_index,
1173 syms, vec_bytes (syms));
1177 elf32_symbol_t *syms;
1179 vec_clone (syms, tab->symbols);
1180 for (i = 0; i < vec_len (tab->symbols); i++)
1182 #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1183 foreach_elf32_symbol_header;
1187 elf_set_section_contents (em, tab->section_index,
1188 syms, vec_bytes (syms));
1193 elf_find_interpreter (elf_main_t * em, void *data)
1199 vec_foreach (g, em->segments)
1201 if (g->header.type == ELF_SEGMENT_INTERP)
1205 if (g >= vec_end (em->segments))
1208 p = hash_get (em->section_by_start_address, g->header.virtual_address);
1212 s = vec_elt_at_index (em->sections, p[0]);
1213 return (char *) vec_dup (s->contents);
1217 elf_get_section_contents_with_starting_address (elf_main_t * em,
1218 uword start_address,
1220 u32 * section_index_result)
1222 elf_section_t *s = 0;
1223 clib_error_t *error;
1225 error = elf_get_section_by_start_address (em, start_address, &s);
1228 clib_error_report (error);
1232 if (section_index_result)
1233 *section_index_result = s->index;
1235 return elf_get_section_contents (em, s->index, elt_size);
1239 elf_parse_dynamic (elf_main_t * em)
1242 elf64_dynamic_entry_t *e;
1244 vec_foreach (s, em->sections)
1246 switch (s->header.type)
1248 case ELF_SECTION_DYNAMIC:
1249 add_dynamic_entries (em, s);
1257 em->dynamic_string_table_section_index = ~0;
1258 em->dynamic_string_table = 0;
1260 vec_foreach (e, em->dynamic_entries)
1264 case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1265 ASSERT (vec_len (em->dynamic_string_table) == 0);
1266 em->dynamic_string_table
1268 elf_get_section_contents_with_starting_address (em, e->data,
1271 dynamic_string_table_section_index);
1274 case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1276 elf_section_t *s = 0;
1277 clib_error_t *error;
1279 error = elf_get_section_by_start_address (em, e->data, &s);
1282 clib_error_report (error);
1286 em->dynamic_symbol_table_section_index = s - em->sections;
1290 case ELF_DYNAMIC_ENTRY_VERSYM:
1293 elf_get_section_contents_with_starting_address (em, e->data,
1297 versym_section_index);
1298 if (em->need_byte_swap)
1301 for (i = 0; i < vec_len (em->versym); i++)
1302 em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1306 case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1309 elf_get_section_contents_with_starting_address (em, e->data,
1313 verneed_section_index);
1314 if (em->need_byte_swap)
1315 byte_swap_verneed (em, em->verneed);
1324 #include <sys/types.h>
1325 #include <sys/stat.h>
1328 __clib_export clib_error_t *
1329 elf_read_file (elf_main_t * em, char *file_name)
1332 struct stat fd_stat;
1333 uword mmap_length = 0;
1335 clib_error_t *error = 0;
1339 fd = open (file_name, 0);
1342 error = clib_error_return_unix (0, "open `%s'", file_name);
1346 if (fstat (fd, &fd_stat) < 0)
1348 error = clib_error_return_unix (0, "fstat `%s'", file_name);
1351 mmap_length = fd_stat.st_size;
1353 data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0);
1354 if (~pointer_to_uword (data) == 0)
1356 error = clib_error_return_unix (0, "mmap `%s'", file_name);
1360 CLIB_MEM_UNPOISON (data, mmap_length);
1362 em->file_name = file_name;
1364 error = elf_parse (em, data, mmap_length);
1368 elf_parse_symbols (em);
1369 elf_parse_dynamic (em);
1371 em->interpreter = elf_find_interpreter (em, data);
1373 munmap (data, mmap_length);
1376 return /* no error */ 0;
1383 munmap (data, mmap_length);
1394 } string_table_builder_t;
1397 string_table_add_name (string_table_builder_t * b, u8 * n)
1401 p = hash_get_mem (b->hash, n);
1405 l = strlen ((char *) n);
1406 i = vec_len (b->new_table);
1407 vec_add (b->new_table, n, l + 1);
1409 for (j = 0; j <= l; j++)
1413 p = hash_get_mem (b->hash, n + j);
1415 /* Sub-string already in table? */
1420 hash_set_mem (b->hash, n + j, i + j);
1426 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1427 __attribute__ ((unused));
1429 string_table_add_name_index (string_table_builder_t * b, u32 index)
1431 u8 *n = b->old_table + index;
1432 return string_table_add_name (b, n);
1435 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1436 __attribute__ ((unused));
1438 string_table_init (string_table_builder_t * b, u8 * old_table)
1440 clib_memset (b, 0, sizeof (b[0]));
1441 b->old_table = old_table;
1442 b->hash = hash_create_string (0, sizeof (uword));
1445 static u8 *string_table_done (string_table_builder_t * b)
1446 __attribute__ ((unused));
1448 string_table_done (string_table_builder_t * b)
1450 hash_free (b->hash);
1451 return b->new_table;
1455 layout_sections (elf_main_t * em)
1458 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 */
1464 /* Re-build section string table (sections may have been deleted). */
1469 vec_foreach (s, em->sections)
1472 if (s->header.type == ~0)
1474 name = elf_section_name (em, s);
1475 s->header.name = vec_len (st);
1476 vec_add (st, name, strlen ((char *) name) + 1);
1480 vec_elt_at_index (em->sections,
1481 em->file_header.section_header_string_table_index);
1483 vec_free (s->contents);
1487 /* Re-build dynamic string table. */
1488 if (rebuild && em->dynamic_string_table_section_index != ~0)
1490 string_table_builder_t b;
1492 string_table_init (&b, em->dynamic_string_table);
1494 /* Add all dynamic symbols. */
1496 elf_symbol_table_t *symtab;
1497 elf64_symbol_t *sym;
1500 vec_elt_at_index (em->symbol_tables,
1501 em->dynamic_symbol_table_index);
1502 vec_foreach (sym, symtab->symbols)
1504 u8 *name = elf_symbol_name (symtab, sym);
1505 sym->name = string_table_add_name (&b, name);
1508 set_symbol_table (em, em->dynamic_symbol_table_index);
1511 /* Add all dynamic entries. */
1513 elf64_dynamic_entry_t *e;
1515 vec_foreach (e, em->dynamic_entries)
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);
1528 /* Add all version needs. */
1529 if (vec_len (em->verneed) > 0)
1531 elf_dynamic_version_need_union_t *n, *a;
1536 n->need.file_name_offset =
1537 string_table_add_name_index (&b, n->need.file_name_offset);
1539 if (n->need.first_aux_offset != 0)
1541 a = n + n->need.first_aux_offset / sizeof (n[0]);
1545 string_table_add_name_index (&b, a->aux.name);
1546 if (a->aux.next_offset == 0)
1548 a += a->aux.next_offset / sizeof (a[0]);
1552 if (n->need.next_offset == 0)
1555 n += n->need.next_offset / sizeof (n[0]);
1558 set_dynamic_verneed (em);
1562 vec_elt_at_index (em->sections,
1563 em->dynamic_string_table_section_index);
1565 vec_free (s->contents);
1566 s->contents = string_table_done (&b);
1568 #endif /* dead code */
1570 /* Figure file offsets and exec addresses for sections. */
1572 u64 exec_address = 0, file_offset = 0;
1573 u64 file_size, align_size;
1575 vec_foreach (s, em->sections)
1577 /* Ignore deleted and unused sections. */
1578 switch (s->header.type)
1581 n_deleted_sections++;
1582 case ELF_SECTION_UNUSED:
1585 case ELF_SECTION_STRING_TABLE:
1586 case ELF_SECTION_SYMBOL_TABLE:
1587 if (!(s->index == em->dynamic_string_table_section_index
1589 em->file_header.section_header_string_table_index))
1591 vec_add1 (deferred_symbol_and_string_sections, s->index);
1600 exec_address = round_pow2_u64 (exec_address, s->header.align);
1602 /* Put sections we added at end of file. */
1603 if (s->header.file_offset == ~0)
1604 s->header.file_offset = file_offset;
1606 /* Follow gaps in original file. */
1607 if (s->header.exec_address > exec_address)
1609 exec_address = s->header.exec_address;
1610 file_offset = s->header.file_offset;
1613 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1615 s->exec_address_change = exec_address - s->header.exec_address;
1616 s->header.exec_address = exec_address;
1619 if (s->header.type == ELF_SECTION_NO_BITS)
1620 file_size = s->header.file_size;
1622 file_size = vec_len (s->contents);
1627 if (s + 1 >= vec_end (em->sections))
1629 else if (s[1].header.type == ELF_SECTION_NO_BITS)
1632 align = s[1].header.align;
1634 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1636 u64 v = round_pow2_u64 (exec_address + file_size, align);
1637 align_size = v - exec_address;
1641 u64 v = round_pow2_u64 (file_offset + file_size, align);
1642 align_size = v - file_offset;
1646 s->header.file_offset = file_offset;
1647 s->header.file_size = file_size;
1648 s->align_size = align_size;
1650 if (s->header.type != ELF_SECTION_NO_BITS)
1651 file_offset += align_size;
1652 exec_address += align_size;
1655 /* Section headers go after last section but before symbol/string
1658 elf64_file_header_t *fh = &em->file_header;
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;
1667 for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1670 vec_elt_at_index (em->sections,
1671 deferred_symbol_and_string_sections[i]);
1673 s->header.file_offset = file_offset;
1674 s->header.file_size = vec_len (s->contents);
1676 align_size = round_pow2 (vec_len (s->contents), 16);
1677 s->align_size = align_size;
1678 file_offset += align_size;
1680 vec_free (deferred_symbol_and_string_sections);
1684 /* Update dynamic entries now that sections have been assigned
1685 possibly new addresses. */
1688 elf_set_dynamic_entries (em);
1691 /* Update segments for changed section addresses. */
1696 vec_foreach (g, em->segments)
1698 u64 s_lo, s_hi, f_lo = 0;
1701 if (g->header.memory_size == 0)
1706 clib_bitmap_foreach (si, g->section_index_bitmap) {
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)
1716 f_lo = s->header.file_offset;
1724 f_lo = s->header.file_offset;
1732 if (n_sections == 0)
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)
1739 s_lo = g->header.virtual_address;
1740 f_lo = g->header.file_offset;
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;
1751 __clib_export clib_error_t *
1752 elf_write_file (elf_main_t *em, char *file_name)
1756 clib_error_t *error = 0;
1758 fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1760 return clib_error_return_unix (0, "open `%s'", file_name);
1762 f = fdopen (fd, "w");
1764 /* Section contents may have changed. So, we need to update
1765 stuff to reflect this. */
1766 layout_sections (em);
1768 /* Write first header. */
1770 elf_first_header_t h = em->first_header;
1772 elf_swap_first_header (em, &h);
1773 if (fwrite (&h, sizeof (h), 1, f) != 1)
1775 error = clib_error_return_unix (0, "write first header");
1780 /* Write file header. */
1782 elf64_file_header_t h = em->file_header;
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);
1789 h.segment_header_file_offset += sizeof (elf32_file_header_t);
1791 if (em->first_header.file_class == ELF_64BIT)
1793 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1794 foreach_elf64_file_header;
1797 if (fwrite (&h, sizeof (h), 1, f) != 1)
1799 error = clib_error_return_unix (0, "write file header");
1805 elf32_file_header_t h32;
1807 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1808 foreach_elf32_file_header;
1811 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1813 error = clib_error_return_unix (0, "write file header");
1819 /* Write segment headers. */
1823 vec_foreach (s, em->segments)
1825 elf64_segment_header_t h;
1827 if (s->header.type == ~0)
1832 if (em->first_header.file_class == ELF_64BIT)
1834 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1835 foreach_elf64_segment_header;
1838 if (fwrite (&h, sizeof (h), 1, f) != 1)
1841 clib_error_return_unix (0, "write segment header %U",
1842 format_elf_segment, em, s);
1848 elf32_segment_header_t h32;
1850 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1851 foreach_elf32_segment_header;
1854 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1857 clib_error_return_unix (0, "write segment header %U",
1858 format_elf_segment, em, s);
1865 /* Write contents for all sections. */
1869 vec_foreach (s, em->sections)
1871 if (s->header.file_size == 0)
1874 if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1877 return clib_error_return_unix (0, "fseek 0x%Lx",
1878 s->header.file_offset);
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)
1886 clib_error_return_unix (0, "write %s section contents",
1887 elf_section_name (em, s));
1892 /* Finally write section headers. */
1893 if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1896 return clib_error_return_unix
1897 (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1900 vec_foreach (s, em->sections)
1902 elf64_section_header_t h;
1904 if (s->header.type == ~0)
1909 if (em->first_header.file_class == ELF_64BIT)
1911 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1912 foreach_elf64_section_header;
1915 if (fwrite (&h, sizeof (h), 1, f) != 1)
1918 clib_error_return_unix (0, "write %s section header",
1919 elf_section_name (em, s));
1925 elf32_section_header_t h32;
1927 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1928 foreach_elf32_section_header;
1931 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1934 clib_error_return_unix (0, "write %s section header",
1935 elf_section_name (em, s));
1948 elf_delete_named_section (elf_main_t * em, char *section_name)
1950 elf_section_t *s = 0;
1951 clib_error_t *error;
1953 error = elf_get_section_by_name (em, section_name, &s);
1957 s->header.type = ~0;
1963 elf_create_section_with_contents (elf_main_t * em,
1965 elf64_section_header_t * header,
1966 void *contents, uword n_content_bytes)
1968 elf_section_t *s, *sts;
1970 uword *p, is_new_section;
1972 /* See if section already exists with given name.
1973 If so, just replace contents. */
1975 if ((p = hash_get_mem (em->section_by_name, section_name)))
1977 s = vec_elt_at_index (em->sections, p[0]);
1978 _vec_len (s->contents) = 0;
1983 vec_add2 (em->sections, s, 1);
1989 vec_elt_at_index (em->sections,
1990 em->file_header.section_header_string_table_index);
1993 s->header = header[0];
1995 s->header.file_offset = ~0;
1996 s->header.file_size = n_content_bytes;
1997 s->index = s - em->sections;
1999 /* Add name to string table. */
2000 s->header.name = vec_len (st);
2001 vec_add (st, section_name, strlen (section_name));
2005 vec_resize (c, n_content_bytes);
2006 clib_memcpy (c, contents, n_content_bytes);
2009 em->file_header.section_header_count += is_new_section
2010 && s->header.type != ~0;
2014 elf_delete_segment_with_type (elf_main_t * em,
2015 elf_segment_type_t segment_type)
2017 uword n_deleted = 0;
2020 vec_foreach (s, em->segments) if (s->header.type == segment_type)
2022 s->header.type = ~0;
2026 ASSERT (em->file_header.segment_header_count >= n_deleted);
2027 em->file_header.segment_header_count -= n_deleted;
2032 #endif /* CLIB_UNIX */
2035 * fd.io coding-style-patch-verification: ON
2038 * eval: (c-set-style "gnu")