FD.io VPP  v19.04.4-rc0-5-ge88582fac
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  em->file_name = file_name;
1361 
1362  error = elf_parse (em, data, mmap_length);
1363  if (error)
1364  goto done;
1365 
1366  elf_parse_symbols (em);
1367  elf_parse_dynamic (em);
1368 
1369  em->interpreter = elf_find_interpreter (em, data);
1370 
1371  munmap (data, mmap_length);
1372  close (fd);
1373 
1374  return /* no error */ 0;
1375 
1376 done:
1377  elf_main_free (em);
1378  if (fd >= 0)
1379  close (fd);
1380  if (data)
1381  munmap (data, mmap_length);
1382  return error;
1383 }
1384 
1385 typedef struct
1386 {
1388 
1390 
1393 
1394 static u32
1396 {
1397  uword *p, i, j, l;
1398 
1399  p = hash_get_mem (b->hash, n);
1400  if (p)
1401  return p[0];
1402 
1403  l = strlen ((char *) n);
1404  i = vec_len (b->new_table);
1405  vec_add (b->new_table, n, l + 1);
1406 
1407  for (j = 0; j <= l; j++)
1408  {
1409  if (j > 0)
1410  {
1411  p = hash_get_mem (b->hash, n + j);
1412 
1413  /* Sub-string already in table? */
1414  if (p)
1415  continue;
1416  }
1417 
1418  hash_set_mem (b->hash, n + j, i + j);
1419  }
1420 
1421  return i;
1422 }
1423 
1425  __attribute__ ((unused));
1426 static u32
1428 {
1429  u8 *n = b->old_table + index;
1430  return string_table_add_name (b, n);
1431 }
1432 
1433 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1434  __attribute__ ((unused));
1435 static void
1437 {
1438  clib_memset (b, 0, sizeof (b[0]));
1439  b->old_table = old_table;
1440  b->hash = hash_create_string (0, sizeof (uword));
1441 }
1442 
1444  __attribute__ ((unused));
1445 static u8 *
1447 {
1448  hash_free (b->hash);
1449  return b->new_table;
1450 }
1451 
1452 static void
1454 {
1455  elf_section_t *s;
1456  u32 n_sections_with_changed_exec_address = 0;
1457  u32 *deferred_symbol_and_string_sections = 0;
1458  u32 n_deleted_sections = 0;
1459  /* note: rebuild is always zero. Intent lost in the sands of time */
1460 #if 0
1461  int rebuild = 0;
1462 
1463  /* Re-build section string table (sections may have been deleted). */
1464  if (rebuild)
1465  {
1466  u8 *st = 0;
1467 
1468  vec_foreach (s, em->sections)
1469  {
1470  u8 *name;
1471  if (s->header.type == ~0)
1472  continue;
1473  name = elf_section_name (em, s);
1474  s->header.name = vec_len (st);
1475  vec_add (st, name, strlen ((char *) name) + 1);
1476  }
1477 
1478  s =
1480  em->file_header.section_header_string_table_index);
1481 
1482  vec_free (s->contents);
1483  s->contents = st;
1484  }
1485 
1486  /* Re-build dynamic string table. */
1487  if (rebuild && em->dynamic_string_table_section_index != ~0)
1488  {
1490 
1492 
1493  /* Add all dynamic symbols. */
1494  {
1495  elf_symbol_table_t *symtab;
1496  elf64_symbol_t *sym;
1497 
1498  symtab =
1501  vec_foreach (sym, symtab->symbols)
1502  {
1503  u8 *name = elf_symbol_name (symtab, sym);
1504  sym->name = string_table_add_name (&b, name);
1505  }
1506 
1508  }
1509 
1510  /* Add all dynamic entries. */
1511  {
1513 
1514  vec_foreach (e, em->dynamic_entries)
1515  {
1516  switch (e->type)
1517  {
1518  case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1519  case ELF_DYNAMIC_ENTRY_RPATH:
1520  case ELF_DYNAMIC_ENTRY_RUN_PATH:
1521  e->data = string_table_add_name_index (&b, e->data);
1522  break;
1523  }
1524  }
1525  }
1526 
1527  /* Add all version needs. */
1528  if (vec_len (em->verneed) > 0)
1529  {
1531 
1532  n = em->verneed;
1533  while (1)
1534  {
1535  n->need.file_name_offset =
1536  string_table_add_name_index (&b, n->need.file_name_offset);
1537 
1538  if (n->need.first_aux_offset != 0)
1539  {
1540  a = n + n->need.first_aux_offset / sizeof (n[0]);
1541  while (1)
1542  {
1543  a->aux.name =
1544  string_table_add_name_index (&b, a->aux.name);
1545  if (a->aux.next_offset == 0)
1546  break;
1547  a += a->aux.next_offset / sizeof (a[0]);
1548  }
1549  }
1550 
1551  if (n->need.next_offset == 0)
1552  break;
1553 
1554  n += n->need.next_offset / sizeof (n[0]);
1555  }
1556 
1557  set_dynamic_verneed (em);
1558  }
1559 
1560  s =
1563 
1564  vec_free (s->contents);
1565  s->contents = string_table_done (&b);
1566  }
1567 #endif /* dead code */
1568 
1569  /* Figure file offsets and exec addresses for sections. */
1570  {
1571  u64 exec_address = 0, file_offset = 0;
1572  u64 file_size, align_size;
1573 
1574  vec_foreach (s, em->sections)
1575  {
1576  /* Ignore deleted and unused sections. */
1577  switch (s->header.type)
1578  {
1579  case ~0:
1580  n_deleted_sections++;
1581  case ELF_SECTION_UNUSED:
1582  continue;
1583 
1584  case ELF_SECTION_STRING_TABLE:
1585  case ELF_SECTION_SYMBOL_TABLE:
1587  || s->index ==
1588  em->file_header.section_header_string_table_index))
1589  {
1590  vec_add1 (deferred_symbol_and_string_sections, s->index);
1591  continue;
1592  }
1593  break;
1594 
1595  default:
1596  break;
1597  }
1598 
1599  exec_address = round_pow2_u64 (exec_address, s->header.align);
1600 
1601  /* Put sections we added at end of file. */
1602  if (s->header.file_offset == ~0)
1603  s->header.file_offset = file_offset;
1604 
1605  /* Follow gaps in original file. */
1606  if (s->header.exec_address > exec_address)
1607  {
1608  exec_address = s->header.exec_address;
1609  file_offset = s->header.file_offset;
1610  }
1611 
1612  if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1613  {
1614  s->exec_address_change = exec_address - s->header.exec_address;
1615  n_sections_with_changed_exec_address += s->exec_address_change != 0;
1616  s->header.exec_address = exec_address;
1617  }
1618 
1619  if (s->header.type == ELF_SECTION_NO_BITS)
1620  file_size = s->header.file_size;
1621  else
1622  file_size = vec_len (s->contents);
1623 
1624  {
1625  u64 align;
1626 
1627  if (s + 1 >= vec_end (em->sections))
1628  align = 16;
1629  else if (s[1].header.type == ELF_SECTION_NO_BITS)
1630  align = 8;
1631  else
1632  align = s[1].header.align;
1633 
1634  if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1635  {
1636  u64 v = round_pow2_u64 (exec_address + file_size, align);
1637  align_size = v - exec_address;
1638  }
1639  else
1640  {
1641  u64 v = round_pow2_u64 (file_offset + file_size, align);
1642  align_size = v - file_offset;
1643  }
1644  }
1645 
1646  s->header.file_offset = file_offset;
1647  s->header.file_size = file_size;
1648  s->align_size = align_size;
1649 
1650  if (s->header.type != ELF_SECTION_NO_BITS)
1651  file_offset += align_size;
1652  exec_address += align_size;
1653  }
1654 
1655  /* Section headers go after last section but before symbol/string
1656  tables. */
1657  {
1658  elf64_file_header_t *fh = &em->file_header;
1659 
1660  fh->section_header_file_offset = file_offset;
1661  fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1662  file_offset += (u64) fh->section_header_count * fh->section_header_size;
1663  }
1664 
1665  {
1666  int i;
1667  for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1668  {
1669  s =
1671  deferred_symbol_and_string_sections[i]);
1672 
1673  s->header.file_offset = file_offset;
1674  s->header.file_size = vec_len (s->contents);
1675 
1676  align_size = round_pow2 (vec_len (s->contents), 16);
1677  s->align_size = align_size;
1678  file_offset += align_size;
1679  }
1680  vec_free (deferred_symbol_and_string_sections);
1681  }
1682  }
1683 
1684  /* Update dynamic entries now that sections have been assigned
1685  possibly new addresses. */
1686 #if 0
1687  if (rebuild)
1689 #endif
1690 
1691  /* Update segments for changed section addresses. */
1692  {
1693  elf_segment_t *g;
1694  uword si;
1695 
1696  vec_foreach (g, em->segments)
1697  {
1698  u64 s_lo, s_hi, f_lo = 0;
1699  u32 n_sections = 0;
1700 
1701  if (g->header.memory_size == 0)
1702  continue;
1703 
1704  s_lo = s_hi = 0;
1705  /* *INDENT-OFF* */
1707  u64 lo, hi;
1708 
1709  s = vec_elt_at_index (em->sections, si);
1710  lo = s->header.exec_address;
1711  hi = lo + s->align_size;
1712  if (n_sections == 0)
1713  {
1714  s_lo = lo;
1715  s_hi = hi;
1716  f_lo = s->header.file_offset;
1717  n_sections++;
1718  }
1719  else
1720  {
1721  if (lo < s_lo)
1722  {
1723  s_lo = lo;
1724  f_lo = s->header.file_offset;
1725  }
1726  if (hi > s_hi)
1727  s_hi = hi;
1728  }
1729  }));
1730  /* *INDENT-ON* */
1731 
1732  if (n_sections == 0)
1733  continue;
1734 
1735  /* File offset zero includes ELF headers/segment headers.
1736  Don't change that. */
1737  if (g->header.file_offset == 0 && g->header.type == ELF_SEGMENT_LOAD)
1738  {
1739  s_lo = g->header.virtual_address;
1740  f_lo = g->header.file_offset;
1741  }
1742 
1743  g->header.virtual_address = s_lo;
1744  g->header.physical_address = s_lo;
1745  g->header.file_offset = f_lo;
1746  g->header.memory_size = s_hi - s_lo;
1747  }
1748  }
1749 }
1750 
1751 clib_error_t *
1752 elf_write_file (elf_main_t * em, char *file_name)
1753 {
1754  int fd;
1755  FILE *f;
1756  clib_error_t *error = 0;
1757 
1758  fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1759  if (fd < 0)
1760  return clib_error_return_unix (0, "open `%s'", file_name);
1761 
1762  f = fdopen (fd, "w");
1763 
1764  /* Section contents may have changed. So, we need to update
1765  stuff to reflect this. */
1766  layout_sections (em);
1767 
1768  /* Write first header. */
1769  {
1771 
1772  elf_swap_first_header (em, &h);
1773  if (fwrite (&h, sizeof (h), 1, f) != 1)
1774  {
1775  error = clib_error_return_unix (0, "write first header");
1776  goto error;
1777  }
1778  }
1779 
1780  /* Write file header. */
1781  {
1783 
1784  /* Segment headers are after first header. */
1785  h.segment_header_file_offset = sizeof (elf_first_header_t);
1786  if (em->first_header.file_class == ELF_64BIT)
1787  h.segment_header_file_offset += sizeof (elf64_file_header_t);
1788  else
1789  h.segment_header_file_offset += sizeof (elf32_file_header_t);
1790 
1791  if (em->first_header.file_class == ELF_64BIT)
1792  {
1793 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1795 #undef _
1796 
1797  if (fwrite (&h, sizeof (h), 1, f) != 1)
1798  {
1799  error = clib_error_return_unix (0, "write file header");
1800  goto error;
1801  }
1802  }
1803  else
1804  {
1805  elf32_file_header_t h32;
1806 
1807 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1809 #undef _
1810 
1811  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1812  {
1813  error = clib_error_return_unix (0, "write file header");
1814  goto error;
1815  }
1816  }
1817  }
1818 
1819  /* Write segment headers. */
1820  {
1821  elf_segment_t *s;
1822 
1823  vec_foreach (s, em->segments)
1824  {
1826 
1827  if (s->header.type == ~0)
1828  continue;
1829 
1830  h = s->header;
1831 
1832  if (em->first_header.file_class == ELF_64BIT)
1833  {
1834 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1836 #undef _
1837 
1838  if (fwrite (&h, sizeof (h), 1, f) != 1)
1839  {
1840  error =
1841  clib_error_return_unix (0, "write segment header %U",
1842  format_elf_segment, em, s);
1843  goto error;
1844  }
1845  }
1846  else
1847  {
1849 
1850 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1852 #undef _
1853 
1854  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1855  {
1856  error =
1857  clib_error_return_unix (0, "write segment header %U",
1858  format_elf_segment, em, s);
1859  goto error;
1860  }
1861  }
1862  }
1863  }
1864 
1865  /* Write contents for all sections. */
1866  {
1867  elf_section_t *s;
1868 
1869  vec_foreach (s, em->sections)
1870  {
1871  if (s->header.file_size == 0)
1872  continue;
1873 
1874  if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1875  {
1876  fclose (f);
1877  return clib_error_return_unix (0, "fseek 0x%Lx",
1878  s->header.file_offset);
1879  }
1880 
1881  if (s->header.type == ELF_SECTION_NO_BITS)
1882  /* don't write for .bss sections */ ;
1883  else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1884  {
1885  error =
1886  clib_error_return_unix (0, "write %s section contents",
1887  elf_section_name (em, s));
1888  goto error;
1889  }
1890  }
1891 
1892  /* Finally write section headers. */
1893  if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1894  {
1895  fclose (f);
1896  return clib_error_return_unix
1897  (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1898  }
1899 
1900  vec_foreach (s, em->sections)
1901  {
1903 
1904  if (s->header.type == ~0)
1905  continue;
1906 
1907  h = s->header;
1908 
1909  if (em->first_header.file_class == ELF_64BIT)
1910  {
1911 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1913 #undef _
1914 
1915  if (fwrite (&h, sizeof (h), 1, f) != 1)
1916  {
1917  error =
1918  clib_error_return_unix (0, "write %s section header",
1919  elf_section_name (em, s));
1920  goto error;
1921  }
1922  }
1923  else
1924  {
1926 
1927 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1929 #undef _
1930 
1931  if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1932  {
1933  error =
1934  clib_error_return_unix (0, "write %s section header",
1935  elf_section_name (em, s));
1936  goto error;
1937  }
1938  }
1939  }
1940  }
1941 
1942 error:
1943  fclose (f);
1944  return error;
1945 }
1946 
1947 clib_error_t *
1948 elf_delete_named_section (elf_main_t * em, char *section_name)
1949 {
1950  elf_section_t *s = 0;
1951  clib_error_t *error;
1952 
1953  error = elf_get_section_by_name (em, section_name, &s);
1954  if (error)
1955  return error;
1956 
1957  s->header.type = ~0;
1958 
1959  return 0;
1960 }
1961 
1962 void
1964  char *section_name,
1965  elf64_section_header_t * header,
1966  void *contents, uword n_content_bytes)
1967 {
1968  elf_section_t *s, *sts;
1969  u8 *st, *c;
1970  uword *p, is_new_section;
1971 
1972  /* See if section already exists with given name.
1973  If so, just replace contents. */
1974  is_new_section = 0;
1975  if ((p = hash_get_mem (em->section_by_name, section_name)))
1976  {
1977  s = vec_elt_at_index (em->sections, p[0]);
1978  _vec_len (s->contents) = 0;
1979  c = s->contents;
1980  }
1981  else
1982  {
1983  vec_add2 (em->sections, s, 1);
1984  is_new_section = 1;
1985  c = 0;
1986  }
1987 
1988  sts =
1990  em->file_header.section_header_string_table_index);
1991  st = sts->contents;
1992 
1993  s->header = header[0];
1994 
1995  s->header.file_offset = ~0;
1996  s->header.file_size = n_content_bytes;
1997  s->index = s - em->sections;
1998 
1999  /* Add name to string table. */
2000  s->header.name = vec_len (st);
2001  vec_add (st, section_name, strlen (section_name));
2002  vec_add1 (st, 0);
2003  sts->contents = st;
2004 
2005  vec_resize (c, n_content_bytes);
2006  clib_memcpy (c, contents, n_content_bytes);
2007  s->contents = c;
2008 
2009  em->file_header.section_header_count += is_new_section
2010  && s->header.type != ~0;
2011 }
2012 
2013 uword
2015  elf_segment_type_t segment_type)
2016 {
2017  uword n_deleted = 0;
2018  elf_segment_t *s;
2019 
2020  vec_foreach (s, em->segments) if (s->header.type == segment_type)
2021  {
2022  s->header.type = ~0;
2023  n_deleted += 1;
2024  }
2025 
2026  ASSERT (em->file_header.segment_header_count >= n_deleted);
2027  em->file_header.segment_header_count -= n_deleted;
2028 
2029  return n_deleted;
2030 }
2031 
2032 #endif /* CLIB_UNIX */
2033 
2034 /*
2035  * fd.io coding-style-patch-verification: ON
2036  *
2037  * Local Variables:
2038  * eval: (c-set-style "gnu")
2039  * End:
2040  */
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
vmrglw vmrglh hi
#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:401
#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:2014
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:522
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:560
int i
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
u8 data[128]
Definition: ipsec.api:248
#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
#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:598
#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 always_inline
Definition: clib.h:98
#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:242
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
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:1752
#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
#define hash_free(h)
Definition: hash.h:310
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:375
#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
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:1427
u8 magic[4]
Definition: elf.h:200
u8 name[64]
Definition: memclnt.api:152
#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
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#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:1453
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:62
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:247
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:241
static u8 * string_table_done(string_table_builder_t *b)
Definition: elf.c:1446
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:1948
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:1436
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:1395
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
#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:980
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:1963
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