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
47 elf_get_section_by_name (elf_main_t * em, char * section_name, elf_section_t ** result)
51 p = hash_get_mem (em->section_by_name, section_name);
53 return clib_error_return (0, "no such section `%s'", section_name);
55 *result = vec_elt_at_index (em->sections, p[0]);
60 elf_get_section_by_start_address_no_check (elf_main_t * em, uword start_address)
62 uword * p = hash_get (em->section_by_start_address, start_address);
63 return p ? vec_elt_at_index (em->sections, p[0]) : 0;
67 elf_get_section_by_start_address (elf_main_t * em, uword start_address, elf_section_t ** result)
69 elf_section_t * s = elf_get_section_by_start_address_no_check (em, start_address);
71 return clib_error_return (0, "no section with address 0x%wx", start_address);
77 format_elf_section_type (u8 * s, va_list * args)
79 elf_section_type_t type = va_arg (*args, elf_section_type_t);
84 #define _(f,i) case ELF_SECTION_##f: t = #f; break;
85 foreach_elf_section_type
90 s = format (s, "unknown 0x%x", type);
92 s = format (s, "%s", t);
97 format_elf_section (u8 * s, va_list * args)
99 elf_main_t * em = va_arg (*args, elf_main_t *);
100 elf_section_t * es = va_arg (*args, elf_section_t *);
101 elf64_section_header_t * h = &es->header;
104 return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s",
105 "Name", "Index", "Type", "Size", "Align", "Address", "File offset");
107 s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx",
108 elf_section_name (em, es),
110 format_elf_section_type, h->type,
114 h->file_offset, h->file_offset + h->file_size);
119 if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f);
120 foreach_elf_section_flag;
128 format_elf_segment_type (u8 * s, va_list * args)
130 elf_segment_type_t type = va_arg (*args, elf_segment_type_t);
135 #define _(f,i) case ELF_SEGMENT_##f: t = #f; break;
136 foreach_elf_segment_type
141 s = format (s, "unknown 0x%x", type);
143 s = format (s, "%s", t);
148 format_elf_segment (u8 * s, va_list * args)
150 elf_segment_t * es = va_arg (*args, elf_segment_t *);
151 elf64_segment_header_t * h = &es->header;
154 return format (s, "%=16s%=16s%=16s%=16s",
155 "Type", "Virt. Address", "Phys. Address", "Size");
157 s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx",
158 format_elf_segment_type, h->type,
167 if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f);
168 foreach_elf_segment_flag;
176 format_elf_symbol_binding_and_type (u8 * s, va_list * args)
178 int bt = va_arg (*args, int);
180 char * type_string = 0;
181 char * binding_string = 0;
183 switch ((b = ((bt >> 4) & 0xf)))
185 #define _(f,n) case n: binding_string = #f; break;
186 foreach_elf_symbol_binding;
191 switch ((t = ((bt >> 0) & 0xf)))
193 #define _(f,n) case n: type_string = #f; break;
194 foreach_elf_symbol_type;
200 s = format (s, "%s", binding_string);
202 s = format (s, "binding 0x%x", b);
205 s = format (s, " %s", type_string);
207 s = format (s, " type 0x%x", t);
213 format_elf_symbol_visibility (u8 * s, va_list * args)
215 int visibility = va_arg (*args, int);
220 #define _(f,n) case n: t = #f; break;
221 foreach_elf_symbol_visibility
226 return format (s, "%s", t);
228 return format (s, "unknown 0x%x", visibility);
232 format_elf_symbol_section_name (u8 * s, va_list * args)
234 elf_main_t * em = va_arg (*args, elf_main_t *);
235 int si = va_arg (*args, int);
238 if (si < vec_len (em->sections))
240 elf_section_t * es = vec_elt_at_index (em->sections, si);
241 return format (s, "%s", elf_section_name (em, es));
244 if (si >= ELF_SYMBOL_SECTION_RESERVED_LO
245 && si <= ELF_SYMBOL_SECTION_RESERVED_HI)
249 #define _(f,n) case n: t = #f; break;
250 foreach_elf_symbol_reserved_section_index
258 return format (s, "%s", t);
260 return format (s, "unknown 0x%x", si);
263 u8 * format_elf_symbol (u8 * s, va_list * args)
265 elf_main_t * em = va_arg (*args, elf_main_t *);
266 elf_symbol_table_t * t = va_arg (*args, elf_symbol_table_t *);
267 elf64_symbol_t * sym = va_arg (*args, elf64_symbol_t *);
270 return format (s, "%=32s%=16s%=16s%=16s%=16s%=16s",
271 "Symbol", "Size", "Value", "Type", "Visibility", "Section");
273 s = format (s, "%-32s%16Ld%16Lx%=16U%=16U%U",
274 elf_symbol_name (t, sym),
275 sym->size, sym->value,
276 format_elf_symbol_binding_and_type, sym->binding_and_type,
277 format_elf_symbol_visibility, sym->visibility,
278 format_elf_symbol_section_name, em, sym->section_index);
284 format_elf_relocation_type (u8 * s, va_list * args)
286 elf_main_t * em = va_arg (*args, elf_main_t *);
287 int type = va_arg (*args, int);
290 switch (em->first_header.architecture)
292 #define _(f,i) [i] = #f,
294 case ELF_ARCH_X86_64:
296 static char * tab[] = {
297 foreach_elf_x86_64_relocation_type
301 if (type < ARRAY_LEN (tab))
311 s = format (s, "0x%02x", type);
313 s = format (s, "%s", t);
319 format_elf_relocation (u8 * s, va_list * args)
321 elf_main_t * em = va_arg (*args, elf_main_t *);
322 elf_relocation_with_addend_t * r = va_arg (*args, elf_relocation_with_addend_t *);
323 elf_symbol_table_t * t;
324 elf64_symbol_t * sym;
327 return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol");
329 t = vec_elt_at_index (em->symbol_tables, 0);
330 sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32);
332 s = format (s, "%16Lx%16U",
334 format_elf_relocation_type, em, r->symbol_and_type & 0xff);
336 if (sym->section_index != 0)
339 es = vec_elt_at_index (em->sections, sym->section_index);
340 s = format (s, " (section %s)", elf_section_name (em, es));
344 s = format (s, " %s", elf_symbol_name (t, sym));
349 s = format (s, " %c 0x%Lx",
358 format_elf_dynamic_entry_type (u8 * s, va_list * args)
360 u32 type = va_arg (*args, u32);
364 #define _(f,n) case n: t = #f; break;
365 foreach_elf_dynamic_entry_type;
370 return format (s, "%s", t);
372 return format (s, "unknown 0x%x", type);
376 format_elf_dynamic_entry (u8 * s, va_list * args)
378 elf_main_t * em = va_arg (*args, elf_main_t *);
379 elf64_dynamic_entry_t * e = va_arg (*args, elf64_dynamic_entry_t *);
382 return format (s, "%=40s%=16s", "Type", "Data");
384 s = format (s, "%=40U",
385 format_elf_dynamic_entry_type, (u32) e->type);
388 case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
389 case ELF_DYNAMIC_ENTRY_RPATH:
390 case ELF_DYNAMIC_ENTRY_RUN_PATH:
391 s = format (s, "%s", em->dynamic_string_table + e->data);
394 case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
395 case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
396 case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
397 case ELF_DYNAMIC_ENTRY_GNU_HASH:
398 case ELF_DYNAMIC_ENTRY_STRING_TABLE:
399 case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
400 case ELF_DYNAMIC_ENTRY_PLT_GOT:
401 case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
402 case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
403 case ELF_DYNAMIC_ENTRY_VERSION_NEED:
404 case ELF_DYNAMIC_ENTRY_VERSYM:
406 elf_section_t * es = elf_get_section_by_start_address_no_check (em, e->data);
408 s = format (s, "section %s", elf_section_name (em, es));
410 s = format (s, "0x%Lx", e->data);
415 s = format (s, "0x%Lx", e->data);
422 static u8 * format_elf_architecture (u8 * s, va_list * args)
424 int a = va_arg (*args, int);
429 #define _(f,n) case n: t = #f; break;
430 foreach_elf_architecture;
433 return format (s, "unknown 0x%x", a);
436 return format (s, "%s", t);
439 static u8 * format_elf_abi (u8 * s, va_list * args)
441 int a = va_arg (*args, int);
446 #define _(f,n) case n: t = #f; break;
450 return format (s, "unknown 0x%x", a);
453 return format (s, "%s", t);
456 static u8 * format_elf_file_class (u8 * s, va_list * args)
458 int a = va_arg (*args, int);
463 #define _(f) case ELF_##f: t = #f; break;
464 foreach_elf_file_class;
467 return format (s, "unknown 0x%x", a);
470 return format (s, "%s", t);
473 static u8 * format_elf_file_type (u8 * s, va_list * args)
475 int a = va_arg (*args, int);
478 if (a >= ELF_ARCH_SPECIFIC_LO && a <= ELF_ARCH_SPECIFIC_HI)
479 return format (s, "arch-specific 0x%x", a - ELF_ARCH_SPECIFIC_LO);
481 if (a >= ELF_OS_SPECIFIC_LO && a <= ELF_OS_SPECIFIC_HI)
482 return format (s, "os-specific 0x%x", a - ELF_OS_SPECIFIC_LO);
486 #define _(f,n) case n: t = #f; break;
487 foreach_elf_file_type;
490 return format (s, "unknown 0x%x", a);
493 return format (s, "%s", t);
496 static u8 * format_elf_data_encoding (u8 * s, va_list * args)
498 int a = va_arg (*args, int);
503 #define _(f) case ELF_##f: t = #f; break;
504 foreach_elf_data_encoding;
507 return format (s, "unknown 0x%x", a);
510 return format (s, "%s", t);
513 static int elf_section_offset_compare (void *a1, void *a2)
515 elf_section_t *s1 = a1;
516 elf_section_t *s2 = a2;
518 return ((i64)s1->header.file_offset - (i64)s2->header.file_offset);
521 static int elf_segment_va_compare (void *a1, void *a2)
523 elf_segment_t *s1 = a1;
524 elf_segment_t *s2 = a2;
526 return ((i64)s1->header.virtual_address - (i64)s2->header.virtual_address);
530 format_elf_main (u8 * s, va_list * args)
532 elf_main_t * em = va_arg (*args, elf_main_t *);
533 u32 verbose = va_arg (*args, u32);
534 elf64_file_header_t * fh = &em->file_header;
536 s = format (s, "File header: machine: %U, file type/class %U/%U, data-encoding: %U, abi: %U version %d\n",
537 format_elf_architecture, em->first_header.architecture,
538 format_elf_file_type, em->first_header.file_type,
539 format_elf_file_class, em->first_header.file_class,
540 format_elf_data_encoding, em->first_header.data_encoding,
541 format_elf_abi, em->first_header.abi, em->first_header.abi_version);
543 s = format (s, " entry 0x%Lx, arch-flags 0x%x",
544 em->file_header.entry_point, em->file_header.flags);
547 s = format (s, "\n interpreter: %s", em->interpreter);
550 elf_section_t * h, * copy;
553 vec_foreach (h, em->sections)
554 if (h->header.type != ~0)
555 vec_add1 (copy, h[0]);
557 vec_sort_with_function (copy, elf_section_offset_compare);
559 s = format (s, "\nSections %d at file offset 0x%Lx-0x%Lx:\n",
560 fh->section_header_count,
561 fh->section_header_file_offset,
562 fh->section_header_file_offset +
563 (u64) fh->section_header_count * fh->section_header_size);
564 s = format (s, "%U\n", format_elf_section, em, 0);
565 vec_foreach (h, copy)
566 s = format (s, "%U\n", format_elf_section, em, h);
572 elf_segment_t * h, * copy;
575 vec_foreach (h, em->segments)
576 if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
577 vec_add1 (copy, h[0]);
579 /* Sort segments by address. */
580 vec_sort_with_function (copy, elf_segment_va_compare);
582 s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n",
583 fh->segment_header_count,
584 fh->segment_header_file_offset,
585 (u64) fh->segment_header_file_offset + (u64) fh->segment_header_count * (u64) fh->segment_header_size);
587 s = format (s, "%U\n", format_elf_segment, 0);
588 vec_foreach (h, copy)
589 s = format (s, "%U\n", format_elf_segment, h);
594 if ((verbose & FORMAT_ELF_MAIN_SYMBOLS)
595 && vec_len (em->symbol_tables) > 0)
597 elf_symbol_table_t * t;
598 elf64_symbol_t * sym;
601 vec_foreach (t, em->symbol_tables)
603 es = vec_elt_at_index (em->sections, t->section_index);
604 s = format (s, "\nSymbols for section %s:\n", elf_section_name (em, es));
606 s = format (s, "%U\n", format_elf_symbol, em, 0, 0);
607 vec_foreach (sym, t->symbols)
608 s = format (s, "%U\n", format_elf_symbol, em, t, sym);
612 if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
613 && vec_len (em->relocation_tables) > 0)
615 elf_relocation_table_t * t;
616 elf_relocation_with_addend_t * r;
619 vec_foreach (t, em->relocation_tables)
621 es = vec_elt_at_index (em->sections, t->section_index);
623 s = format (s, "\nRelocations for section %s:\n",
624 elf_section_name (em, es));
626 s = format (s, "%U\n", format_elf_relocation, em, 0);
627 vec_foreach (r, t->relocations)
629 s = format (s, "%U\n",
630 format_elf_relocation, em, r);
635 if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
636 && vec_len (em->dynamic_entries) > 0)
638 elf64_dynamic_entry_t * es, * e;
639 s = format (s, "\nDynamic linker information:\n");
640 es = vec_dup (em->dynamic_entries);
641 s = format (s, "%U\n", format_elf_dynamic_entry, em, 0);
643 s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
650 elf_parse_segments (elf_main_t * em, void * data)
652 void * d = data + em->file_header.segment_header_file_offset;
653 uword n = em->file_header.segment_header_count;
656 vec_resize (em->segments, n);
658 for (i = 0; i < n; i++)
660 em->segments[i].index = i;
662 if (em->first_header.file_class == ELF_64BIT)
664 elf64_segment_header_t * h = d;
665 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
666 foreach_elf64_segment_header
672 elf32_segment_header_t * h = d;
673 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
674 foreach_elf32_segment_header
682 elf_parse_sections (elf_main_t * em, void * data)
684 elf64_file_header_t * fh = &em->file_header;
686 void * d = data + fh->section_header_file_offset;
687 uword n = fh->section_header_count;
690 vec_resize (em->sections, n);
692 for (i = 0; i < n; i++)
694 s = em->sections + i;
698 if (em->first_header.file_class == ELF_64BIT)
700 elf64_section_header_t * h = d;
701 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
702 foreach_elf64_section_header
708 elf32_section_header_t * h = d;
709 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
710 foreach_elf32_section_header
715 if (s->header.type != ELF_SECTION_NO_BITS)
716 vec_add (s->contents, data + s->header.file_offset, s->header.file_size);
719 s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
722 = hash_create_string (/* # elts */ vec_len (em->sections),
723 /* sizeof of value */ sizeof (uword));
725 vec_foreach (s, em->sections)
727 hash_set_mem (em->section_by_name,
728 elf_section_name (em, s),
730 hash_set (em->section_by_start_address,
731 s->header.exec_address,
737 add_symbol_table (elf_main_t * em, elf_section_t * s)
739 elf_symbol_table_t * tab;
740 elf32_symbol_t * sym32;
741 elf64_symbol_t * sym64;
744 if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
745 em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
747 vec_add2 (em->symbol_tables, tab, 1);
749 tab->section_index = s->index;
751 if (em->first_header.file_class == ELF_64BIT)
753 tab->symbols = elf_get_section_contents (em, s - em->sections, sizeof (tab->symbols[0]));
754 for (i = 0; i < vec_len (tab->symbols); i++)
756 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
757 foreach_elf64_symbol_header;
763 sym32 = elf_get_section_contents (em, s - em->sections, sizeof (sym32[0]));
764 vec_clone (tab->symbols, sym32);
765 for (i = 0; i < vec_len (tab->symbols); i++)
767 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
768 foreach_elf32_symbol_header;
773 if (s->header.link == 0)
777 elf_get_section_contents (em, s->header.link, sizeof (tab->string_table[0]));
779 = hash_create_string (/* # elts */ vec_len (tab->symbols),
780 /* sizeof of value */ sizeof (uword));
782 vec_foreach (sym64, tab->symbols)
784 if (sym64->name != 0)
785 hash_set_mem (tab->symbol_by_name,
786 tab->string_table + sym64->name,
787 sym64 - tab->symbols);
792 add_relocation_table (elf_main_t * em, elf_section_t * s)
794 uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
795 elf_relocation_table_t * t;
798 vec_add2 (em->relocation_tables, t, 1);
799 t->section_index = s - em->sections;
801 if (em->first_header.file_class == ELF_64BIT)
803 elf64_relocation_t * r, * rs;
805 rs = elf_get_section_contents (em, t->section_index,
806 sizeof (rs[0]) + has_addend * sizeof (rs->addend[0]));
808 if (em->need_byte_swap)
811 for (i = 0; i < vec_len (r); i++)
813 r->address = elf_swap_u64 (em, r->address);
814 r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
816 r->addend[0] = elf_swap_u64 (em, r->addend[0]);
817 r = elf_relocation_next (r, s->header.type);
821 vec_resize (t->relocations, vec_len (rs));
822 clib_memcpy (t->relocations, rs, vec_bytes (t->relocations));
827 elf_relocation_with_addend_t * r;
828 elf32_relocation_t * r32, * r32s;
830 r32s = elf_get_section_contents (em, t->section_index,
831 sizeof (r32s[0]) + has_addend * sizeof (r32s->addend[0]));
832 vec_resize (t->relocations, vec_len (r32s));
835 vec_foreach (r, t->relocations)
837 r->address = elf_swap_u32 (em, r32->address);
838 r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
839 r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0;
840 r32 = elf_relocation_next (r32, s->header.type);
847 void elf_parse_symbols (elf_main_t * em)
851 /* No need to parse symbols twice. */
852 if (em->parsed_symbols)
854 em->parsed_symbols = 1;
856 vec_foreach (s, em->sections)
858 switch (s->header.type)
860 case ELF_SECTION_SYMBOL_TABLE:
861 case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
862 add_symbol_table (em, s);
865 case ELF_SECTION_RELOCATION_ADD:
866 case ELF_SECTION_RELOCATION:
867 add_relocation_table (em, s);
876 void elf_set_dynamic_entries (elf_main_t * em)
880 /* Start address for sections may have changed. */
882 elf64_dynamic_entry_t * e;
884 vec_foreach (e, em->dynamic_entries)
888 case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
889 case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
890 case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
891 case ELF_DYNAMIC_ENTRY_GNU_HASH:
892 case ELF_DYNAMIC_ENTRY_STRING_TABLE:
893 case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
894 case ELF_DYNAMIC_ENTRY_PLT_GOT:
895 case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
896 case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
897 case ELF_DYNAMIC_ENTRY_VERSION_NEED:
898 case ELF_DYNAMIC_ENTRY_VERSYM:
900 elf_section_t * es = elf_get_section_by_start_address_no_check (em, e->data);
901 /* If section is not found just leave e->data alone. */
903 e->data = es->header.exec_address;
913 if (em->first_header.file_class == ELF_64BIT)
915 elf64_dynamic_entry_t * e, * es;
917 es = em->dynamic_entries;
918 if (em->need_byte_swap)
923 e->type = elf_swap_u64 (em, e->type);
924 e->data = elf_swap_u64 (em, e->data);
928 elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
929 if (es != em->dynamic_entries)
934 elf32_dynamic_entry_t * es;
936 vec_clone (es, em->dynamic_entries);
937 if (em->need_byte_swap)
939 for (i = 0; i < vec_len (es); i++)
941 es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type);
942 es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data);
946 elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
952 elf_parse (elf_main_t * em,
956 elf_first_header_t * h = data;
957 elf64_file_header_t * fh = &em->file_header;
958 clib_error_t * error = 0;
961 char * save = em->file_name;
962 memset (em, 0, sizeof (em[0]));
963 em->file_name = save;
966 em->first_header = h[0];
968 CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding == ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
969 elf_swap_first_header (em, &em->first_header);
971 if (! (h->magic[0] == 0x7f
972 && h->magic[1] == 'E'
973 && h->magic[2] == 'L'
974 && h->magic[3] == 'F'))
975 return clib_error_return (0, "`%s': bad magic", em->file_name);
977 if (h->file_class == ELF_64BIT)
979 elf64_file_header_t * h64 = (void *) (h + 1);
980 #define _(t,f) fh->f = elf_swap_##t (em, h64->f);
981 foreach_elf64_file_header
986 elf32_file_header_t * h32 = (void *) (h + 1);
988 #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
989 foreach_elf32_file_header
993 elf_parse_segments (em, data);
994 elf_parse_sections (em, data);
996 /* Figure which sections are contained in each segment. */
1000 vec_foreach (g, em->segments)
1005 if (g->header.memory_size == 0)
1008 g_lo = g->header.virtual_address;
1009 g_hi = g_lo + g->header.memory_size;
1011 vec_foreach (s, em->sections)
1013 s_lo = s->header.exec_address;
1014 s_hi = s_lo + s->header.file_size;
1016 if (s_lo >= g_lo && s_hi <= g_hi)
1018 g->section_index_bitmap = clib_bitmap_ori (g->section_index_bitmap, s->index);
1019 s->segment_index_bitmap = clib_bitmap_ori (s->segment_index_bitmap, g->index);
1031 add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1035 /* Can't have more than one dynamic section. */
1036 ASSERT (em->dynamic_section_index == 0);
1037 em->dynamic_section_index = s->index;
1039 if (em->first_header.file_class == ELF_64BIT)
1041 elf64_dynamic_entry_t * e;
1043 e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1044 if (em->need_byte_swap)
1045 for (i = 0; i < vec_len (e); i++)
1047 e[i].type = elf_swap_u64 (em, e[i].type);
1048 e[i].data = elf_swap_u64 (em, e[i].data);
1051 em->dynamic_entries = e;
1055 elf32_dynamic_entry_t * e;
1057 e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1058 vec_clone (em->dynamic_entries, e);
1059 if (em->need_byte_swap)
1060 for (i = 0; i < vec_len (e); i++)
1062 em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type);
1063 em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data);
1070 static void byte_swap_verneed (elf_main_t * em,
1071 elf_dynamic_version_need_union_t * vus)
1073 uword * entries_swapped = 0;
1076 for (i = 0; i < vec_len (vus); i++)
1078 elf_dynamic_version_need_union_t * n = vec_elt_at_index (vus, i);
1079 elf_dynamic_version_need_union_t * a;
1081 if (clib_bitmap_get (entries_swapped, i))
1084 elf_swap_verneed (&n->need);
1085 entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1087 if (n->need.first_aux_offset != 0)
1089 ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1090 j = i + (n->need.first_aux_offset / sizeof (n[0]));
1093 a = vec_elt_at_index (vus, j);
1094 if (! clib_bitmap_get (entries_swapped, j))
1096 entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1097 elf_swap_verneed_aux (&a->aux);
1099 if (a->aux.next_offset == 0)
1101 ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1102 j += (a->aux.next_offset / sizeof (a->aux));
1107 clib_bitmap_free (entries_swapped);
1111 set_dynamic_verneed (elf_main_t * em) __attribute__((unused));
1113 set_dynamic_verneed (elf_main_t * em)
1115 elf_dynamic_version_need_union_t * vus = em->verneed;
1117 if (em->need_byte_swap)
1119 vus = vec_dup (vus);
1120 byte_swap_verneed (em, vus);
1123 elf_set_section_contents (em, em->verneed_section_index, vus, vec_bytes (vus));
1124 if (vus != em->verneed)
1129 set_symbol_table (elf_main_t * em, u32 table_index) __attribute__((unused));
1131 set_symbol_table (elf_main_t * em, u32 table_index)
1133 elf_symbol_table_t * tab = vec_elt_at_index (em->symbol_tables, table_index);
1135 if (em->first_header.file_class == ELF_64BIT)
1137 elf64_symbol_t * s, * syms;
1139 syms = vec_dup (tab->symbols);
1140 vec_foreach (s, syms)
1142 #define _(t,f) s->f = elf_swap_##t (em, s->f);
1143 foreach_elf64_symbol_header;
1147 elf_set_section_contents (em, tab->section_index,
1148 syms, vec_bytes (syms));
1152 elf32_symbol_t * syms;
1154 vec_clone (syms, tab->symbols);
1155 for (i = 0; i < vec_len (tab->symbols); i++)
1157 #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1158 foreach_elf32_symbol_header;
1162 elf_set_section_contents (em, tab->section_index,
1163 syms, vec_bytes (syms));
1168 elf_find_interpreter (elf_main_t * em, void * data)
1174 vec_foreach (g, em->segments)
1176 if (g->header.type == ELF_SEGMENT_INTERP)
1180 if (g >= vec_end (em->segments))
1183 p = hash_get (em->section_by_start_address, g->header.virtual_address);
1187 s = vec_elt_at_index (em->sections, p[0]);
1188 return (char *) vec_dup (s->contents);
1192 elf_get_section_contents_with_starting_address (elf_main_t * em,
1193 uword start_address,
1195 u32 * section_index_result)
1198 clib_error_t * error;
1200 error = elf_get_section_by_start_address (em, start_address, &s);
1203 clib_error_report (error);
1207 if (section_index_result)
1208 *section_index_result = s->index;
1210 return elf_get_section_contents (em, s->index, elt_size);
1213 static void elf_parse_dynamic (elf_main_t * em)
1216 elf64_dynamic_entry_t * e;
1218 vec_foreach (s, em->sections)
1220 switch (s->header.type)
1222 case ELF_SECTION_DYNAMIC:
1223 add_dynamic_entries (em, s);
1231 em->dynamic_string_table_section_index = ~0;
1232 em->dynamic_string_table = 0;
1234 vec_foreach (e, em->dynamic_entries)
1238 case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1239 ASSERT (vec_len (em->dynamic_string_table) == 0);
1240 em->dynamic_string_table
1241 = elf_get_section_contents_with_starting_address (em, e->data, sizeof (u8),
1242 &em->dynamic_string_table_section_index);
1245 case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1248 clib_error_t * error;
1250 error = elf_get_section_by_start_address (em, e->data, &s);
1253 clib_error_report (error);
1257 em->dynamic_symbol_table_section_index = s - em->sections;
1261 case ELF_DYNAMIC_ENTRY_VERSYM:
1263 = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->versym[0]),
1264 &em->versym_section_index);
1265 if (em->need_byte_swap)
1268 for (i = 0; i < vec_len (em->versym); i++)
1269 em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1273 case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1275 = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->verneed[0]),
1276 &em->verneed_section_index);
1277 if (em->need_byte_swap)
1278 byte_swap_verneed (em, em->verneed);
1287 #include <sys/types.h>
1288 #include <sys/stat.h>
1291 clib_error_t * elf_read_file (elf_main_t * em, char * file_name)
1294 struct stat fd_stat;
1295 uword mmap_length = 0;
1297 clib_error_t * error = 0;
1301 fd = open (file_name, 0);
1304 error = clib_error_return_unix (0, "open `%s'", file_name);
1308 if (fstat (fd, &fd_stat) < 0)
1310 error = clib_error_return_unix (0, "fstat `%s'", file_name);
1313 mmap_length = fd_stat.st_size;
1315 data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0);
1316 if (~pointer_to_uword (data) == 0)
1318 error = clib_error_return_unix (0, "mmap `%s'", file_name);
1322 em->file_name = file_name;
1324 error = elf_parse (em, data, mmap_length);
1328 elf_parse_symbols (em);
1329 elf_parse_dynamic (em);
1331 em->interpreter = elf_find_interpreter (em, data);
1333 munmap (data, mmap_length);
1336 return /* no error */ 0;
1343 munmap (data, mmap_length);
1353 } string_table_builder_t;
1355 static u32 string_table_add_name (string_table_builder_t * b, u8 * n)
1359 p = hash_get_mem (b->hash, n);
1362 l = strlen ((char *) n);
1363 i = vec_len (b->new_table);
1364 vec_add (b->new_table, n, l + 1);
1366 for (j = 0; j <= l; j++)
1370 p = hash_get_mem (b->hash, n + j);
1372 /* Sub-string already in table? */
1377 hash_set_mem (b->hash, n + j, i + j);
1383 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1384 __attribute__((unused));
1385 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1387 u8 * n = b->old_table + index;
1388 return string_table_add_name (b, n);
1391 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1392 __attribute__((unused));
1393 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1395 memset (b, 0, sizeof (b[0]));
1396 b->old_table = old_table;
1397 b->hash = hash_create_string (0, sizeof (uword));
1400 static u8 * string_table_done (string_table_builder_t * b)
1401 __attribute__((unused));
1402 static u8 * string_table_done (string_table_builder_t * b)
1404 hash_free (b->hash);
1405 return b->new_table;
1408 static void layout_sections (elf_main_t * em)
1411 u32 n_sections_with_changed_exec_address = 0;
1412 u32 * deferred_symbol_and_string_sections = 0;
1413 u32 n_deleted_sections = 0;
1414 /* note: rebuild is always zero. Intent lost in the sands of time */
1418 /* Re-build section string table (sections may have been deleted). */
1423 vec_foreach (s, em->sections)
1426 if (s->header.type == ~0)
1428 name = elf_section_name (em, s);
1429 s->header.name = vec_len (st);
1430 vec_add (st, name, strlen ((char *) name) + 1);
1433 s = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1435 vec_free (s->contents);
1439 /* Re-build dynamic string table. */
1440 if (rebuild && em->dynamic_string_table_section_index != ~0)
1442 string_table_builder_t b;
1444 string_table_init (&b, em->dynamic_string_table);
1446 /* Add all dynamic symbols. */
1448 elf_symbol_table_t * symtab;
1449 elf64_symbol_t * sym;
1451 symtab = vec_elt_at_index (em->symbol_tables, em->dynamic_symbol_table_index);
1452 vec_foreach (sym, symtab->symbols)
1454 u8 * name = elf_symbol_name (symtab, sym);
1455 sym->name = string_table_add_name (&b, name);
1458 set_symbol_table (em, em->dynamic_symbol_table_index);
1461 /* Add all dynamic entries. */
1463 elf64_dynamic_entry_t * e;
1465 vec_foreach (e, em->dynamic_entries)
1469 case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1470 case ELF_DYNAMIC_ENTRY_RPATH:
1471 case ELF_DYNAMIC_ENTRY_RUN_PATH:
1472 e->data = string_table_add_name_index (&b, e->data);
1478 /* Add all version needs. */
1479 if (vec_len (em->verneed) > 0)
1481 elf_dynamic_version_need_union_t * n, * a;
1486 n->need.file_name_offset = string_table_add_name_index (&b, n->need.file_name_offset);
1488 if (n->need.first_aux_offset != 0)
1490 a = n + n->need.first_aux_offset / sizeof (n[0]);
1493 a->aux.name = string_table_add_name_index (&b, a->aux.name);
1494 if (a->aux.next_offset == 0)
1496 a += a->aux.next_offset / sizeof (a[0]);
1500 if (n->need.next_offset == 0)
1503 n += n->need.next_offset / sizeof (n[0]);
1506 set_dynamic_verneed (em);
1509 s = vec_elt_at_index (em->sections, em->dynamic_string_table_section_index);
1511 vec_free (s->contents);
1512 s->contents = string_table_done (&b);
1514 #endif /* dead code */
1516 /* Figure file offsets and exec addresses for sections. */
1518 u64 exec_address = 0, file_offset = 0;
1519 u64 file_size, align_size;
1521 vec_foreach (s, em->sections)
1523 /* Ignore deleted and unused sections. */
1524 switch (s->header.type)
1527 n_deleted_sections++;
1528 case ELF_SECTION_UNUSED:
1531 case ELF_SECTION_STRING_TABLE:
1532 case ELF_SECTION_SYMBOL_TABLE:
1533 if (! (s->index == em->dynamic_string_table_section_index
1534 || s->index == em->file_header.section_header_string_table_index))
1536 vec_add1 (deferred_symbol_and_string_sections, s->index);
1545 exec_address = round_pow2_u64 (exec_address, s->header.align);
1547 /* Put sections we added at end of file. */
1548 if (s->header.file_offset == ~0)
1549 s->header.file_offset = file_offset;
1551 /* Follow gaps in original file. */
1552 if (s->header.exec_address > exec_address)
1554 exec_address = s->header.exec_address;
1555 file_offset = s->header.file_offset;
1558 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1560 s->exec_address_change = exec_address - s->header.exec_address;
1561 n_sections_with_changed_exec_address += s->exec_address_change != 0;
1562 s->header.exec_address = exec_address;
1565 if (s->header.type == ELF_SECTION_NO_BITS)
1566 file_size = s->header.file_size;
1568 file_size = vec_len (s->contents);
1573 if (s + 1 >= vec_end (em->sections))
1575 else if (s[1].header.type == ELF_SECTION_NO_BITS)
1578 align = s[1].header.align;
1580 if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1582 u64 v = round_pow2_u64 (exec_address + file_size, align);
1583 align_size = v - exec_address;
1587 u64 v = round_pow2_u64 (file_offset + file_size, align);
1588 align_size = v - file_offset;
1592 s->header.file_offset = file_offset;
1593 s->header.file_size = file_size;
1594 s->align_size = align_size;
1596 if (s->header.type != ELF_SECTION_NO_BITS)
1597 file_offset += align_size;
1598 exec_address += align_size;
1601 /* Section headers go after last section but before symbol/string
1604 elf64_file_header_t * fh = &em->file_header;
1606 fh->section_header_file_offset = file_offset;
1607 fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1608 file_offset += (u64) fh->section_header_count * fh->section_header_size;
1613 for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1615 s = vec_elt_at_index (em->sections, deferred_symbol_and_string_sections[i]);
1617 s->header.file_offset = file_offset;
1618 s->header.file_size = vec_len (s->contents);
1620 align_size = round_pow2 (vec_len (s->contents), 16);
1621 s->align_size = align_size;
1622 file_offset += align_size;
1624 vec_free (deferred_symbol_and_string_sections);
1628 /* Update dynamic entries now that sections have been assigned
1629 possibly new addresses. */
1632 elf_set_dynamic_entries (em);
1635 /* Update segments for changed section addresses. */
1640 vec_foreach (g, em->segments)
1642 u64 s_lo, s_hi, f_lo = 0;
1645 if (g->header.memory_size == 0)
1649 clib_bitmap_foreach (si, g->section_index_bitmap, ({
1652 s = vec_elt_at_index (em->sections, si);
1653 lo = s->header.exec_address;
1654 hi = lo + s->align_size;
1655 if (n_sections == 0)
1659 f_lo = s->header.file_offset;
1667 f_lo = s->header.file_offset;
1674 if (n_sections == 0)
1677 /* File offset zero includes ELF headers/segment headers.
1678 Don't change that. */
1679 if (g->header.file_offset == 0
1680 && g->header.type == ELF_SEGMENT_LOAD)
1682 s_lo = g->header.virtual_address;
1683 f_lo = g->header.file_offset;
1686 g->header.virtual_address = s_lo;
1687 g->header.physical_address = s_lo;
1688 g->header.file_offset = f_lo;
1689 g->header.memory_size = s_hi - s_lo;
1694 clib_error_t * elf_write_file (elf_main_t * em, char * file_name)
1698 clib_error_t * error = 0;
1700 fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1702 return clib_error_return_unix (0, "open `%s'", file_name);
1704 f = fdopen (fd, "w");
1706 /* Section contents may have changed. So, we need to update
1707 stuff to reflect this. */
1708 layout_sections (em);
1710 /* Write first header. */
1712 elf_first_header_t h = em->first_header;
1714 elf_swap_first_header (em, &h);
1715 if (fwrite (&h, sizeof (h), 1, f) != 1)
1717 error = clib_error_return_unix (0, "write first header");
1722 /* Write file header. */
1724 elf64_file_header_t h = em->file_header;
1726 /* Segment headers are after first header. */
1727 h.segment_header_file_offset = sizeof (elf_first_header_t);
1728 if (em->first_header.file_class == ELF_64BIT)
1729 h.segment_header_file_offset += sizeof (elf64_file_header_t);
1731 h.segment_header_file_offset += sizeof (elf32_file_header_t);
1733 if (em->first_header.file_class == ELF_64BIT)
1735 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1736 foreach_elf64_file_header;
1739 if (fwrite (&h, sizeof (h), 1, f) != 1)
1741 error = clib_error_return_unix (0, "write file header");
1747 elf32_file_header_t h32;
1749 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1750 foreach_elf32_file_header;
1753 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1755 error = clib_error_return_unix (0, "write file header");
1761 /* Write segment headers. */
1765 vec_foreach (s, em->segments)
1767 elf64_segment_header_t h;
1769 if (s->header.type == ~0)
1774 if (em->first_header.file_class == ELF_64BIT)
1776 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1777 foreach_elf64_segment_header;
1780 if (fwrite (&h, sizeof (h), 1, f) != 1)
1782 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1788 elf32_segment_header_t h32;
1790 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1791 foreach_elf32_segment_header;
1794 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1796 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1803 /* Write contents for all sections. */
1807 vec_foreach (s, em->sections)
1809 if (s->header.file_size == 0)
1812 if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1815 return clib_error_return_unix (0, "fseek 0x%Lx",
1816 s->header.file_offset);
1819 if (s->header.type == ELF_SECTION_NO_BITS)
1820 /* don't write for .bss sections */;
1821 else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1823 error = clib_error_return_unix (0, "write %s section contents", elf_section_name (em, s));
1828 /* Finally write section headers. */
1829 if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1832 return clib_error_return_unix
1833 (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1836 vec_foreach (s, em->sections)
1838 elf64_section_header_t h;
1840 if (s->header.type == ~0)
1845 if (em->first_header.file_class == ELF_64BIT)
1847 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1848 foreach_elf64_section_header;
1851 if (fwrite (&h, sizeof (h), 1, f) != 1)
1853 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1859 elf32_section_header_t h32;
1861 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1862 foreach_elf32_section_header;
1865 if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1867 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1879 clib_error_t * elf_delete_named_section (elf_main_t * em, char * section_name)
1882 clib_error_t * error;
1884 error = elf_get_section_by_name (em, section_name, &s);
1888 s->header.type = ~0;
1894 elf_create_section_with_contents (elf_main_t * em,
1895 char * section_name,
1896 elf64_section_header_t * header,
1898 uword n_content_bytes)
1900 elf_section_t * s, * sts;
1902 uword * p, is_new_section;
1904 /* See if section already exists with given name.
1905 If so, just replace contents. */
1907 if ((p = hash_get_mem (em->section_by_name, section_name)))
1909 s = vec_elt_at_index (em->sections, p[0]);
1910 _vec_len (s->contents) = 0;
1915 vec_add2 (em->sections, s, 1);
1920 sts = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1923 s->header = header[0];
1925 s->header.file_offset = ~0;
1926 s->header.file_size = n_content_bytes;
1927 s->index = s - em->sections;
1929 /* Add name to string table. */
1930 s->header.name = vec_len (st);
1931 vec_add (st, section_name, strlen (section_name));
1935 vec_resize (c, n_content_bytes);
1936 clib_memcpy (c, contents, n_content_bytes);
1939 em->file_header.section_header_count += is_new_section && s->header.type != ~0;
1942 uword elf_delete_segment_with_type (elf_main_t * em, elf_segment_type_t segment_type)
1944 uword n_deleted = 0;
1947 vec_foreach (s, em->segments)
1948 if (s->header.type == segment_type)
1950 s->header.type = ~0;
1954 ASSERT (em->file_header.segment_header_count >= n_deleted);
1955 em->file_header.segment_header_count -= n_deleted;
1960 #endif /* CLIB_UNIX */