FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
elf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vppinfra/bitmap.h>
16 #include <vppinfra/byte_order.h>
17 #include <vppinfra/error.h>
18 #include <vppinfra/hash.h>
19 #include <vppinfra/vec.h>
20 #include <vppinfra/elf.h>
21 
22 always_inline void
24 {
26  h->file_type = elf_swap_u16 (em, h->file_type);
28 }
29 
30 always_inline void
32 {
33 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
35 #undef _
36 }
37 
38 always_inline void
40 {
41 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
43 #undef _
44 }
45 
47 elf_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 
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 
70  elf_section_t ** result)
71 {
72  elf_section_t *s =
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 
81 static u8 *
82 format_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;
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 
101 static u8 *
102 format_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 *);
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);
126 #undef _
127  }
128 
129  return s;
130 }
131 
132 static u8 *
133 format_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;
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 
152 static u8 *
153 format_elf_segment (u8 * s, va_list * args)
154 {
155  elf_segment_t *es = va_arg (*args, elf_segment_t *);
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);
172 #undef _
173  }
174 
175  return s;
176 }
177 
178 static u8 *
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;
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;
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 
217 static u8 *
218 format_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;
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 
236 static u8 *
237 format_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 
251  {
252  switch (si)
253  {
254 #define _(f,n) case n: t = #f; break;
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 
268 u8 *
269 format_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 
290 static u8 *
291 format_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[] = {
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 
325 static u8 *
326 format_elf_relocation (u8 * s, va_list * args)
327 {
328  elf_main_t *em = va_arg (*args, elf_main_t *);
330  va_arg (*args, elf_relocation_with_addend_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,
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 
363 static u8 *
364 format_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;
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 
382 static u8 *
383 format_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 =
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 
429 static u8 *
430 format_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;
439 #undef _
440  default:
441  return format (s, "unknown 0x%x", a);
442  }
443 
444  return format (s, "%s", t);
445 }
446 
447 static u8 *
448 format_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;
457 #undef _
458  default:
459  return format (s, "unknown 0x%x", a);
460  }
461 
462  return format (s, "%s", t);
463 }
464 
465 static u8 *
466 format_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;
475 #undef _
476  default:
477  return format (s, "unknown 0x%x", a);
478  }
479 
480  return format (s, "%s", t);
481 }
482 
483 static u8 *
484 format_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;
499 #undef _
500  default:
501  return format (s, "unknown 0x%x", a);
502  }
503 
504  return format (s, "%s", t);
505 }
506 
507 static u8 *
508 format_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;
517 #undef _
518  default:
519  return format (s, "unknown 0x%x", a);
520  }
521 
522  return format (s, "%s", t);
523 }
524 
525 static int
526 elf_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 
534 static int
535 elf_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 
544 u8 *
545 format_elf_main (u8 * s, va_list * args)
546 {
547  elf_main_t *em = va_arg (*args, elf_main_t *);
548  u32 verbose = va_arg (*args, u32);
549  elf64_file_header_t *fh = &em->file_header;
550 
551  s =
552  format (s,
553  "File header: machine: %U, file type/class %U/%U, data-encoding: %U, abi: %U version %d\n",
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 
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. */
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  {
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  {
635  elf_section_t *es;
636 
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 
666 static void
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  {
682 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
684 #undef _
685  d = (h + 1);
686  }
687  else
688  {
690 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
692 #undef _
693  d = (h + 1);
694  }
695  }
696 }
697 
698 static void
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  {
718 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
720 #undef _
721  d = (h + 1);
722  }
723  else
724  {
726 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
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  {
746  elf_section_name (em, s), s - em->sections);
748  s->header.exec_address, s - em->sections);
749  }
750 }
751 
752 static void
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)
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);
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);
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)
806  tab->string_table + sym64->name, sym64 - tab->symbols);
807  }
808 }
809 
810 static void
812 {
813  uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
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 
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);
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));
843  vec_free (rs);
844  }
845  else
846  {
848  elf32_relocation_t *r32, *r32s;
849 
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);
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 
868 void
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 
898 void
900 {
901  uword i;
902 
903  /* Start address for sections may have changed. */
904  {
906 
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 =
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 
953  vec_bytes (es));
954  if (es != em->dynamic_entries)
955  vec_free (es);
956  }
957  else
958  {
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 
972  vec_bytes (es));
973  vec_free (es);
974  }
975 }
976 
977 clib_error_t *
978 elf_parse (elf_main_t * em, void *data, uword data_bytes)
979 {
981  elf64_file_header_t *fh = &em->file_header;
982  clib_error_t *error = 0;
983 
984  {
985  char *save = em->file_name;
986  clib_memset (em, 0, sizeof (em[0]));
987  em->file_name = save;
988  }
989 
990  em->first_header = h[0];
991  em->need_byte_swap =
993  ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
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);
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);
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  {
1042  clib_bitmap_ori (g->section_index_bitmap, s->index);
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 
1055 static void
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  {
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  {
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 
1095 static void
1097 {
1098  uword *entries_swapped = 0;
1099  uword i, j;
1100 
1101  for (i = 0; i < vec_len (vus); i++)
1102  {
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 
1135 static void set_dynamic_verneed (elf_main_t * em) __attribute__ ((unused));
1136 static void
1138 {
1140 
1141  if (em->need_byte_swap)
1142  {
1143  vus = vec_dup (vus);
1144  byte_swap_verneed (em, vus);
1145  }
1146 
1148  vec_bytes (vus));
1149  if (vus != em->verneed)
1150  vec_free (vus);
1151 }
1152 
1153 static void
1154 set_symbol_table (elf_main_t * em, u32 table_index) __attribute__ ((unused));
1155 static void
1156 set_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);
1169 #undef _
1170  }
1171 
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);
1184 #undef _
1185  }
1186 
1188  syms, vec_bytes (syms));
1189  }
1190 }
1191 
1192 static char *
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 
1216 static void *
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 
1238 static void
1240 {
1241  elf_section_t *s;
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 
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);
1267  =
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 
1287  }
1288  break;
1289 
1290  case ELF_DYNAMIC_ENTRY_VERSYM:
1291  em->versym
1292  =
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  =
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 
1328 clib_error_t *
1329 elf_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 
1360  CLIB_MEM_UNPOISON (data, mmap_length);
1361 
1362  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 
1378 done:
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 
1387 typedef struct
1388 {
1390 
1392 
1395 
1396 static u32
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 
1427  __attribute__ ((unused));
1428 static u32
1430 {
1431  u8 *n = b->old_table + index;
1432  return string_table_add_name (b, n);
1433 }
1434 
1435 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1436  __attribute__ ((unused));
1437 static void
1439 {
1440  clib_memset (b, 0, sizeof (b[0]));
1441  b->old_table = old_table;
1442  b->hash = hash_create_string (0, sizeof (uword));
1443 }
1444 
1446  __attribute__ ((unused));
1447 static u8 *
1449 {
1450  hash_free (b->hash);
1451  return b->new_table;
1452 }
1453 
1454 static void
1456 {
1457  elf_section_t *s;
1458  u32 n_sections_with_changed_exec_address = 0;
1459  u32 *deferred_symbol_and_string_sections = 0;
1460  u32 n_deleted_sections = 0;
1461  /* note: rebuild is always zero. Intent lost in the sands of time */
1462 #if 0
1463  int rebuild = 0;
1464 
1465  /* Re-build section string table (sections may have been deleted). */
1466  if (rebuild)
1467  {
1468  u8 *st = 0;
1469 
1470  vec_foreach (s, em->sections)
1471  {
1472  u8 *name;
1473  if (s->header.type == ~0)
1474  continue;
1475  name = elf_section_name (em, s);
1476  s->header.name = vec_len (st);
1477  vec_add (st, name, strlen ((char *) name) + 1);
1478  }
1479 
1480  s =
1482  em->file_header.section_header_string_table_index);
1483 
1484  vec_free (s->contents);
1485  s->contents = st;
1486  }
1487 
1488  /* Re-build dynamic string table. */
1489  if (rebuild && em->dynamic_string_table_section_index != ~0)
1490  {
1492 
1494 
1495  /* Add all dynamic symbols. */
1496  {
1497  elf_symbol_table_t *symtab;
1498  elf64_symbol_t *sym;
1499 
1500  symtab =
1503  vec_foreach (sym, symtab->symbols)
1504  {
1505  u8 *name = elf_symbol_name (symtab, sym);
1506  sym->name = string_table_add_name (&b, name);
1507  }
1508 
1510  }
1511 
1512  /* Add all dynamic entries. */
1513  {
1515 
1516  vec_foreach (e, em->dynamic_entries)
1517  {
1518  switch (e->type)
1519  {
1520  case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1521  case ELF_DYNAMIC_ENTRY_RPATH:
1522  case ELF_DYNAMIC_ENTRY_RUN_PATH:
1523  e->data = string_table_add_name_index (&b, e->data);
1524  break;
1525  }
1526  }
1527  }
1528 
1529  /* Add all version needs. */
1530  if (vec_len (em->verneed) > 0)
1531  {
1533 
1534  n = em->verneed;
1535  while (1)
1536  {
1537  n->need.file_name_offset =
1538  string_table_add_name_index (&b, n->need.file_name_offset);
1539 
1540  if (n->need.first_aux_offset != 0)
1541  {
1542  a = n + n->need.first_aux_offset / sizeof (n[0]);
1543  while (1)
1544  {
1545  a->aux.name =
1546  string_table_add_name_index (&b, a->aux.name);
1547  if (a->aux.next_offset == 0)
1548  break;
1549  a += a->aux.next_offset / sizeof (a[0]);
1550  }
1551  }
1552 
1553  if (n->need.next_offset == 0)
1554  break;
1555 
1556  n += n->need.next_offset / sizeof (n[0]);
1557  }
1558 
1559  set_dynamic_verneed (em);
1560  }
1561 
1562  s =
1565 
1566  vec_free (s->contents);
1567  s->contents = string_table_done (&b);
1568  }
1569 #endif /* dead code */
1570 
1571  /* Figure file offsets and exec addresses for sections. */
1572  {
1573  u64 exec_address = 0, file_offset = 0;
1574  u64 file_size, align_size;
1575 
1576  vec_foreach (s, em->sections)
1577  {
1578  /* Ignore deleted and unused sections. */
1579  switch (s->header.type)
1580  {
1581  case ~0:
1582  n_deleted_sections++;
1583  case ELF_SECTION_UNUSED:
1584  continue;
1585 
1586  case ELF_SECTION_STRING_TABLE:
1587  case ELF_SECTION_SYMBOL_TABLE:
1589  || s->index ==
1590  em->file_header.section_header_string_table_index))
1591  {
1592  vec_add1 (deferred_symbol_and_string_sections, s->index);
1593  continue;
1594  }
1595  break;
1596 
1597  default:
1598  break;
1599  }
1600 
1601  exec_address = round_pow2_u64 (exec_address, s->header.align);
1602 
1603  /* Put sections we added at end of file. */
1604  if (s->header.file_offset == ~0)
1605  s->header.file_offset = file_offset;
1606 
1607  /* Follow gaps in original file. */
1608  if (s->header.exec_address > exec_address)
1609  {
1610  exec_address = s->header.exec_address;
1611  file_offset = s->header.file_offset;
1612  }
1613 
1614  if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1615  {
1616  s->exec_address_change = exec_address - s->header.exec_address;
1617  n_sections_with_changed_exec_address += s->exec_address_change != 0;
1618  s->header.exec_address = exec_address;
1619  }
1620 
1621  if (s->header.type == ELF_SECTION_NO_BITS)
1622  file_size = s->header.file_size;
1623  else
1624  file_size = vec_len (s->contents);
1625 
1626  {
1627  u64 align;
1628 
1629  if (s + 1 >= vec_end (em->sections))
1630  align = 16;
1631  else if (s[1].header.type == ELF_SECTION_NO_BITS)
1632  align = 8;
1633  else
1634  align = s[1].header.align;
1635 
1636  if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1637  {
1638  u64 v = round_pow2_u64 (exec_address + file_size, align);
1639  align_size = v - exec_address;
1640  }
1641  else
1642  {
1643  u64 v = round_pow2_u64 (file_offset + file_size, align);
1644  align_size = v - file_offset;
1645  }
1646  }
1647 
1648  s->header.file_offset = file_offset;
1649  s->header.file_size = file_size;
1650  s->align_size = align_size;
1651 
1652  if (s->header.type != ELF_SECTION_NO_BITS)
1653  file_offset += align_size;
1654  exec_address += align_size;
1655  }
1656 
1657  /* Section headers go after last section but before symbol/string
1658  tables. */
1659  {
1660  elf64_file_header_t *fh = &em->file_header;
1661 
1662  fh->section_header_file_offset = file_offset;
1663  fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1664  file_offset += (u64) fh->section_header_count * fh->section_header_size;
1665  }
1666 
1667  {
1668  int i;
1669  for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1670  {
1671  s =
1673  deferred_symbol_and_string_sections[i]);
1674 
1675  s->header.file_offset = file_offset;
1676  s->header.file_size = vec_len (s->contents);
1677 
1678  align_size = round_pow2 (vec_len (s->contents), 16);
1679  s->align_size = align_size;
1680  file_offset += align_size;
1681  }
1682  vec_free (deferred_symbol_and_string_sections);
1683  }
1684  }
1685 
1686  /* Update dynamic entries now that sections have been assigned
1687  possibly new addresses. */
1688 #if 0
1689  if (rebuild)
1691 #endif
1692 
1693  /* Update segments for changed section addresses. */
1694  {
1695  elf_segment_t *g;
1696  uword si;
1697 
1698  vec_foreach (g, em->segments)
1699  {
1700  u64 s_lo, s_hi, f_lo = 0;
1701  u32 n_sections = 0;
1702 
1703  if (g->header.memory_size == 0)
1704  continue;
1705 
1706  s_lo = s_hi = 0;
1707  /* *INDENT-OFF* */
1709  u64 lo, hi;
1710 
1711  s = vec_elt_at_index (em->sections, si);
1712  lo = s->header.exec_address;
1713  hi = lo + s->align_size;
1714  if (n_sections == 0)
1715  {
1716  s_lo = lo;
1717  s_hi = hi;
1718  f_lo = s->header.file_offset;
1719  n_sections++;
1720  }
1721  else
1722  {
1723  if (lo < s_lo)
1724  {
1725  s_lo = lo;
1726  f_lo = s->header.file_offset;
1727  }
1728  if (hi > s_hi)
1729  s_hi = hi;
1730  }
1731  }));
1732  /* *INDENT-ON* */
1733 
1734  if (n_sections == 0)
1735  continue;
1736 
1737  /* File offset zero includes ELF headers/segment headers.
1738  Don't change that. */
1739  if (g->header.file_offset == 0 && g->header.type == ELF_SEGMENT_LOAD)
1740  {
1741  s_lo = g->header.virtual_address;
1742  f_lo = g->header.file_offset;
1743  }
1744 
1745  g->header.virtual_address = s_lo;
1746  g->header.physical_address = s_lo;
1747  g->header.file_offset = f_lo;
1748  g->header.memory_size = s_hi - s_lo;
1749  }
1750  }
1751 }
1752 
1753 clib_error_t *
1754 elf_write_file (elf_main_t * em, char *file_name)
1755 {
1756  int fd;
1757  FILE *f;
1758  clib_error_t *error = 0;
1759 
1760  fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1761  if (fd < 0)
1762  return clib_error_return_unix (0, "open `%s'", file_name);
1763 
1764  f = fdopen (fd, "w");
1765 
1766  /* Section contents may have changed. So, we need to update
1767  stuff to reflect this. */
1768  layout_sections (em);
1769 
1770  /* Write first header. */
1771  {
1773 
1774  elf_swap_first_header (em, &h);
1775  if (fwrite (&h, sizeof (h), 1, f) != 1)
1776  {
1777  error = clib_error_return_unix (0, "write first header");
1778  goto error;
1779  }
1780  }
1781 
1782  /* Write file header. */
1783  {
1785 
1786  /* Segment headers are after first header. */
1787  h.segment_header_file_offset = sizeof (elf_first_header_t);
1788  if (em->first_header.file_class == ELF_64BIT)
1789  h.segment_header_file_offset += sizeof (elf64_file_header_t);
1790  else
1791  h.segment_header_file_offset += sizeof (elf32_file_header_t);
1792 
1793  if (em->first_header.file_class == ELF_64BIT)
1794  {
1795 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1797 #undef _
1798 
1799  if (fwrite (&h, sizeof (h), 1, f) != 1)
1800  {
1801  error = clib_error_return_unix (0, "write file header");
1802  goto error;
1803  }
1804  }
1805  else
1806  {
1807  elf32_file_header_t h32;
1808 
1809 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1811 #undef _
1812 
1813  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1814  {
1815  error = clib_error_return_unix (0, "write file header");
1816  goto error;
1817  }
1818  }
1819  }
1820 
1821  /* Write segment headers. */
1822  {
1823  elf_segment_t *s;
1824 
1825  vec_foreach (s, em->segments)
1826  {
1828 
1829  if (s->header.type == ~0)
1830  continue;
1831 
1832  h = s->header;
1833 
1834  if (em->first_header.file_class == ELF_64BIT)
1835  {
1836 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1838 #undef _
1839 
1840  if (fwrite (&h, sizeof (h), 1, f) != 1)
1841  {
1842  error =
1843  clib_error_return_unix (0, "write segment header %U",
1844  format_elf_segment, em, s);
1845  goto error;
1846  }
1847  }
1848  else
1849  {
1851 
1852 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1854 #undef _
1855 
1856  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1857  {
1858  error =
1859  clib_error_return_unix (0, "write segment header %U",
1860  format_elf_segment, em, s);
1861  goto error;
1862  }
1863  }
1864  }
1865  }
1866 
1867  /* Write contents for all sections. */
1868  {
1869  elf_section_t *s;
1870 
1871  vec_foreach (s, em->sections)
1872  {
1873  if (s->header.file_size == 0)
1874  continue;
1875 
1876  if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1877  {
1878  fclose (f);
1879  return clib_error_return_unix (0, "fseek 0x%Lx",
1880  s->header.file_offset);
1881  }
1882 
1883  if (s->header.type == ELF_SECTION_NO_BITS)
1884  /* don't write for .bss sections */ ;
1885  else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1886  {
1887  error =
1888  clib_error_return_unix (0, "write %s section contents",
1889  elf_section_name (em, s));
1890  goto error;
1891  }
1892  }
1893 
1894  /* Finally write section headers. */
1895  if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1896  {
1897  fclose (f);
1898  return clib_error_return_unix
1899  (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1900  }
1901 
1902  vec_foreach (s, em->sections)
1903  {
1905 
1906  if (s->header.type == ~0)
1907  continue;
1908 
1909  h = s->header;
1910 
1911  if (em->first_header.file_class == ELF_64BIT)
1912  {
1913 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1915 #undef _
1916 
1917  if (fwrite (&h, sizeof (h), 1, f) != 1)
1918  {
1919  error =
1920  clib_error_return_unix (0, "write %s section header",
1921  elf_section_name (em, s));
1922  goto error;
1923  }
1924  }
1925  else
1926  {
1928 
1929 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1931 #undef _
1932 
1933  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1934  {
1935  error =
1936  clib_error_return_unix (0, "write %s section header",
1937  elf_section_name (em, s));
1938  goto error;
1939  }
1940  }
1941  }
1942  }
1943 
1944 error:
1945  fclose (f);
1946  return error;
1947 }
1948 
1949 clib_error_t *
1950 elf_delete_named_section (elf_main_t * em, char *section_name)
1951 {
1952  elf_section_t *s = 0;
1953  clib_error_t *error;
1954 
1955  error = elf_get_section_by_name (em, section_name, &s);
1956  if (error)
1957  return error;
1958 
1959  s->header.type = ~0;
1960 
1961  return 0;
1962 }
1963 
1964 void
1966  char *section_name,
1967  elf64_section_header_t * header,
1968  void *contents, uword n_content_bytes)
1969 {
1970  elf_section_t *s, *sts;
1971  u8 *st, *c;
1972  uword *p, is_new_section;
1973 
1974  /* See if section already exists with given name.
1975  If so, just replace contents. */
1976  is_new_section = 0;
1977  if ((p = hash_get_mem (em->section_by_name, section_name)))
1978  {
1979  s = vec_elt_at_index (em->sections, p[0]);
1980  _vec_len (s->contents) = 0;
1981  c = s->contents;
1982  }
1983  else
1984  {
1985  vec_add2 (em->sections, s, 1);
1986  is_new_section = 1;
1987  c = 0;
1988  }
1989 
1990  sts =
1992  em->file_header.section_header_string_table_index);
1993  st = sts->contents;
1994 
1995  s->header = header[0];
1996 
1997  s->header.file_offset = ~0;
1998  s->header.file_size = n_content_bytes;
1999  s->index = s - em->sections;
2000 
2001  /* Add name to string table. */
2002  s->header.name = vec_len (st);
2003  vec_add (st, section_name, strlen (section_name));
2004  vec_add1 (st, 0);
2005  sts->contents = st;
2006 
2007  vec_resize (c, n_content_bytes);
2008  clib_memcpy (c, contents, n_content_bytes);
2009  s->contents = c;
2010 
2011  em->file_header.section_header_count += is_new_section
2012  && s->header.type != ~0;
2013 }
2014 
2015 uword
2017  elf_segment_type_t segment_type)
2018 {
2019  uword n_deleted = 0;
2020  elf_segment_t *s;
2021 
2022  vec_foreach (s, em->segments) if (s->header.type == segment_type)
2023  {
2024  s->header.type = ~0;
2025  n_deleted += 1;
2026  }
2027 
2028  ASSERT (em->file_header.segment_header_count >= n_deleted);
2029  em->file_header.segment_header_count -= n_deleted;
2030 
2031  return n_deleted;
2032 }
2033 
2034 #endif /* CLIB_UNIX */
2035 
2036 /*
2037  * fd.io coding-style-patch-verification: ON
2038  *
2039  * Local Variables:
2040  * eval: (c-set-style "gnu")
2041  * End:
2042  */
static u8 * format_elf_file_type(u8 *s, va_list *args)
Definition: elf.c:484
u8 * format_elf_main(u8 *s, va_list *args)
Definition: elf.c:545
#define ELF_SYMBOL_SECTION_RESERVED_HI
Definition: elf.h:347
static u8 * format_elf_symbol_section_name(u8 *s, va_list *args)
Definition: elf.c:237
static void elf_main_free(elf_main_t *em)
Definition: elf.h:926
static u32 elf_swap_u32(elf_main_t *em, u32 x)
Definition: elf.h:1015
elf64_segment_header_t header
Definition: elf.h:873
#define vec_clone(NEW_V, OLD_V)
Clone a vector.
Definition: vec.h:455
#define CLIB_MEM_UNPOISON(a, s)
Definition: sanitizer.h:47
#define hash_set(h, key, value)
Definition: hash.h:255
static u8 * elf_section_name(elf_main_t *em, elf_section_t *s)
Definition: elf.h:994
u8 need_byte_swap
Definition: elf.h:885
u32 verneed_section_index
Definition: elf.h:916
a
Definition: bitmap.h:538
static u8 * format_elf_section_type(u8 *s, va_list *args)
Definition: elf.c:82
static u8 * format_elf_segment_type(u8 *s, va_list *args)
Definition: elf.c:133
#define foreach_elf32_section_header
Definition: elf.h:242
#define foreach_elf64_section_header
Definition: elf.h:254
unsigned long u64
Definition: types.h:89
uword elf_delete_segment_with_type(elf_main_t *em, elf_segment_type_t segment_type)
Definition: elf.c:2016
elf_data_encoding_t data_encoding
Definition: elf.h:203
void elf_set_dynamic_entries(elf_main_t *em)
Definition: elf.c:899
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: elf.h:857
i32 addend[0]
Definition: elf.h:482
static void elf_parse_dynamic(elf_main_t *em)
Definition: elf.c:1239
i64 exec_address_change
Definition: elf.h:866
static void elf_swap_first_header(elf_main_t *em, elf_first_header_t *h)
Definition: elf.c:23
static u8 * format_elf_relocation(u8 *s, va_list *args)
Definition: elf.c:326
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static void elf_swap_verneed(elf_dynamic_version_need_t *n)
Definition: elf.c:31
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
#define hash_set_mem(h, key, value)
Definition: hash.h:275
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static u8 * format_elf_dynamic_entry(u8 *s, va_list *args)
Definition: elf.c:383
#define foreach_elf_section_type
Definition: elf.h:354
void elf_parse_symbols(elf_main_t *em)
Definition: elf.c:869
#define vec_bytes(v)
Number of data bytes in vector.
u32 dynamic_section_index
Definition: elf.h:912
static u64 elf_swap_u64(elf_main_t *em, u64 x)
Definition: elf.h:1021
elf_section_type_t
Definition: elf.h:402
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:89
#define FORMAT_ELF_MAIN_RELOCATIONS
Definition: elf.h:1027
#define foreach_elf64_file_header
Definition: elf.h:229
#define clib_memcpy(d, s, n)
Definition: string.h:180
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:668
#define foreach_elf_dynamic_version_need_aux_field
Definition: elf.h:718
u8 * contents
Definition: elf.h:868
#define foreach_elf64_symbol_header
Definition: elf.h:297
uword * section_index_bitmap
Definition: elf.h:876
uword * section_by_name
Definition: elf.h:899
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
static void add_symbol_table(elf_main_t *em, elf_section_t *s)
Definition: elf.c:753
#define foreach_elf32_segment_header
Definition: elf.h:267
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:281
unsigned int u32
Definition: types.h:88
#define vec_end(v)
End (last data address) of vector.
#define foreach_elf_file_class
Definition: elf.h:46
elf_abi_t abi
Definition: elf.h:205
static u8 * format_elf_abi(u8 *s, va_list *args)
Definition: elf.c:448
static void set_symbol_table(elf_main_t *em, u32 table_index)
Definition: elf.c:1156
elf_symbol_table_t * symbol_tables
Definition: elf.h:902
static u8 * format_elf_data_encoding(u8 *s, va_list *args)
Definition: elf.c:508
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
#define foreach_elf_dynamic_version_need_field
Definition: elf.h:711
elf_dynamic_version_need_aux_t aux
Definition: elf.h:742
vl_api_fib_path_type_t type
Definition: fib_types.api:123
elf_segment_t * segments
Definition: elf.h:895
#define hash_get(h, key)
Definition: hash.h:249
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
clib_error_t * elf_write_file(elf_main_t *em, char *file_name)
Definition: elf.c:1754
#define foreach_elf_symbol_visibility
Definition: elf.h:449
static void add_relocation_table(elf_main_t *em, elf_section_t *s)
Definition: elf.c:811
u64 align_size
Definition: elf.h:864
u32 file_version
Definition: elf.h:213
u8 * dynamic_string_table
Definition: elf.h:908
signed long i64
Definition: types.h:78
#define clib_error_return_unix(e, args...)
Definition: error.h:102
static void elf_swap_verneed_aux(elf_dynamic_version_need_aux_t *n)
Definition: elf.c:39
vec_header_t h
Definition: buffer.c:322
#define hash_free(h)
Definition: hash.h:310
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:429
#define foreach_elf_data_encoding
Definition: elf.h:49
#define elf_relocation_next(r, type)
Definition: elf.h:499
static u8 * format_elf_segment(u8 *s, va_list *args)
Definition: elf.c:153
Definition: elf.h:563
#define foreach_elf64_segment_header
Definition: elf.h:277
#define always_inline
Definition: ipsec.h:28
static void byte_swap_verneed(elf_main_t *em, elf_dynamic_version_need_union_t *vus)
Definition: elf.c:1096
static u32 string_table_add_name_index(string_table_builder_t *b, u32 index)
Definition: elf.c:1429
u8 magic[4]
Definition: elf.h:200
#define foreach_elf32_file_header
Definition: elf.h:217
u64 symbol_and_type
Definition: elf.h:488
static void elf_set_section_contents(elf_main_t *em, uword section_index, void *new_contents, uword n_content_bytes)
Definition: elf.h:982
static void * elf_get_section_contents_with_starting_address(elf_main_t *em, uword start_address, uword elt_size, u32 *section_index_result)
Definition: elf.c:1217
elf_first_header_t first_header
Definition: elf.h:891
Definition: elf.h:567
svmdb_client_t * c
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define foreach_elf32_symbol_header
Definition: elf.h:288
clib_error_t * elf_read_file(elf_main_t *em, char *file_name)
Definition: elf.c:1329
elf_relocation_with_addend_t * relocations
Definition: elf.h:842
u32 section_index
Definition: elf.h:820
static u8 * format_elf_architecture(u8 *s, va_list *args)
Definition: elf.c:430
static void set_dynamic_verneed(elf_main_t *em)
Definition: elf.c:1137
static void layout_sections(elf_main_t *em)
Definition: elf.c:1455
u32 index
Definition: elf.h:878
elf_architecture_t architecture
Definition: elf.h:211
elf64_symbol_t * symbols
Definition: elf.h:818
static void elf_main_init(elf_main_t *em)
Definition: elf.h:920
static u8 * format_elf_dynamic_entry_type(u8 *s, va_list *args)
Definition: elf.c:364
#define ARRAY_LEN(x)
Definition: clib.h:67
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
static u64 round_pow2_u64(u64 x, u64 pow2)
Definition: clib.h:270
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:264
string name[64]
Definition: ip.api:44
static u8 * string_table_done(string_table_builder_t *b)
Definition: elf.c:1448
static int elf_segment_va_compare(void *a1, void *a2)
Definition: elf.c:535
#define foreach_elf_x86_64_relocation_type
Definition: elf.h:790
static void elf_parse_segments(elf_main_t *em, void *data)
Definition: elf.c:667
clib_error_t * elf_delete_named_section(elf_main_t *em, char *section_name)
Definition: elf.c:1950
u32 dynamic_symbol_table_section_index
Definition: elf.h:910
static u8 * format_elf_section(u8 *s, va_list *args)
Definition: elf.c:102
#define ASSERT(truth)
char * file_name
Definition: elf.h:889
static void string_table_init(string_table_builder_t *b, u8 *old_table)
Definition: elf.c:1438
static int elf_section_offset_compare(void *a1, void *a2)
Definition: elf.c:526
static void * elf_get_section_contents(elf_main_t *em, uword section_index, uword elt_size)
Definition: elf.h:958
elf64_dynamic_entry_t * dynamic_entries
Definition: elf.h:907
i64 addend[0]
Definition: elf.h:489
static u32 string_table_add_name(string_table_builder_t *b, u8 *n)
Definition: elf.c:1397
Bitmaps built as vectors of machine words.
elf_segment_type_t
Definition: elf.h:532
#define clib_error_report(e)
Definition: error.h:113
static void elf_parse_sections(elf_main_t *em, void *data)
Definition: elf.c:699
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u8 parsed_symbols
Definition: elf.h:887
elf_relocation_table_t * relocation_tables
Definition: elf.h:903
elf_section_t * sections
Definition: elf.h:897
u8 * string_table
Definition: elf.h:822
static void add_dynamic_entries(elf_main_t *em, elf_section_t *s)
Definition: elf.c:1056
static u8 * format_elf_relocation_type(u8 *s, va_list *args)
Definition: elf.c:291
static uword pointer_to_uword(const void *p)
Definition: types.h:131
elf_dynamic_version_need_t need
Definition: elf.h:741
#define FORMAT_ELF_MAIN_SYMBOLS
Definition: elf.h:1026
vl_api_ip4_address_t hi
Definition: arp.api:37
#define foreach_elf_symbol_binding
Definition: elf.h:425
#define CLIB_ARCH_IS_BIG_ENDIAN
Definition: byte_order.h:44
u8 * format_elf_symbol(u8 *s, va_list *args)
Definition: elf.c:269
#define FORMAT_ELF_MAIN_DYNAMIC
Definition: elf.h:1028
#define ELF_SYMBOL_SECTION_RESERVED_LO
Definition: elf.h:346
#define foreach_elf_symbol_reserved_section_index
Definition: elf.h:341
static u8 * elf_symbol_name(elf_symbol_table_t *t, elf64_symbol_t *sym)
Definition: elf.h:835
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
clib_error_t * elf_parse(elf_main_t *em, void *data, uword data_bytes)
Definition: elf.c:978
uword * symbol_by_name
Definition: elf.h:824
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
u32 index
Definition: flow_types.api:221
static u8 * format_elf_file_class(u8 *s, va_list *args)
Definition: elf.c:466
uword * segment_index_bitmap
Definition: elf.h:860
elf64_file_header_t file_header
Definition: elf.h:893
elf_section_t * elf_get_section_by_start_address_no_check(elf_main_t *em, uword start_address)
Definition: elf.c:61
#define hash_get_mem(h, key)
Definition: hash.h:269
#define foreach_elf_symbol_type
Definition: elf.h:435
u32 dynamic_symbol_table_index
Definition: elf.h:911
char * interpreter
Definition: elf.h:905
elf64_section_header_t header
Definition: elf.h:855
#define vec_foreach(var, vec)
Vector iterator.
elf_dynamic_version_need_union_t * verneed
Definition: elf.h:915
u16 * versym
Definition: elf.h:913
static u8 * format_elf_symbol_visibility(u8 *s, va_list *args)
Definition: elf.c:218
void elf_create_section_with_contents(elf_main_t *em, char *section_name, elf64_section_header_t *header, void *contents, uword n_content_bytes)
Definition: elf.c:1965
u8 si
Definition: lisp_types.api:47
clib_error_t * elf_get_section_by_name(elf_main_t *em, char *section_name, elf_section_t **result)
Definition: elf.c:47
static u16 elf_swap_u16(elf_main_t *em, u16 x)
Definition: elf.h:1009
elf_file_type_t file_type
Definition: elf.h:210
static u16 clib_byte_swap_u16(u16 x)
Definition: byte_order.h:57
static u8 * format_elf_symbol_binding_and_type(u8 *s, va_list *args)
Definition: elf.c:179
clib_error_t * elf_get_section_by_start_address(elf_main_t *em, uword start_address, elf_section_t **result)
Definition: elf.c:69
elf_file_class_t file_class
Definition: elf.h:202
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
static char * elf_find_interpreter(elf_main_t *em, void *data)
Definition: elf.c:1193
uword * section_by_start_address
Definition: elf.h:900
u32 dynamic_string_table_section_index
Definition: elf.h:909