misc: asan: mark parsed elf memory as readable for ASan
[vpp.git] / src / vppinfra / elf.c
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
23 elf_swap_first_header (elf_main_t * em, elf_first_header_t * h)
24 {
25   h->architecture = elf_swap_u16 (em, h->architecture);
26   h->file_type = elf_swap_u16 (em, h->file_type);
27   h->file_version = elf_swap_u32 (em, h->file_version);
28 }
29
30 always_inline void
31 elf_swap_verneed (elf_dynamic_version_need_t * n)
32 {
33 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
34   foreach_elf_dynamic_version_need_field
35 #undef _
36 }
37
38 always_inline void
39 elf_swap_verneed_aux (elf_dynamic_version_need_aux_t * n)
40 {
41 #define _(t,f) n->f = clib_byte_swap_##t (n->f);
42   foreach_elf_dynamic_version_need_aux_field
43 #undef _
44 }
45
46 clib_error_t *
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
60 elf_section_t *
61 elf_get_section_by_start_address_no_check (elf_main_t * em,
62                                            uword start_address)
63 {
64   uword *p = hash_get (em->section_by_start_address, start_address);
65   return p ? vec_elt_at_index (em->sections, p[0]) : 0;
66 }
67
68 clib_error_t *
69 elf_get_section_by_start_address (elf_main_t * em, uword start_address,
70                                   elf_section_t ** result)
71 {
72   elf_section_t *s =
73     elf_get_section_by_start_address_no_check (em, start_address);
74   if (!s)
75     return clib_error_return (0, "no section with address 0x%wx",
76                               start_address);
77   *result = s;
78   return 0;
79 }
80
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;
90       foreach_elf_section_type
91 #undef _
92     }
93
94   if (!t)
95     s = format (s, "unknown 0x%x", type);
96   else
97     s = format (s, "%s", t);
98   return s;
99 }
100
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 *);
106   elf64_section_header_t *h = &es->header;
107
108   if (!h)
109     return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s",
110                    "Name", "Index", "Type", "Size", "Align", "Address",
111                    "File offset");
112
113   s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx",
114               elf_section_name (em, es),
115               es->index,
116               format_elf_section_type, h->type,
117               h->file_size,
118               h->align,
119               h->exec_address, h->file_offset, h->file_offset + h->file_size);
120
121   if (h->flags != 0)
122     {
123 #define _(f,i) \
124   if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f);
125       foreach_elf_section_flag;
126 #undef _
127     }
128
129   return s;
130 }
131
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;
141       foreach_elf_segment_type
142 #undef _
143     }
144
145   if (!t)
146     s = format (s, "unknown 0x%x", type);
147   else
148     s = format (s, "%s", t);
149   return s;
150 }
151
152 static u8 *
153 format_elf_segment (u8 * s, va_list * args)
154 {
155   elf_segment_t *es = va_arg (*args, elf_segment_t *);
156   elf64_segment_header_t *h = &es->header;
157
158   if (!h)
159     return format (s, "%=16s%=16s%=16s%=16s",
160                    "Type", "Virt. Address", "Phys. Address", "Size");
161
162   s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx",
163               format_elf_segment_type, h->type,
164               h->virtual_address,
165               h->physical_address, h->memory_size, h->file_offset);
166
167   if (h->flags != 0)
168     {
169 #define _(f,i) \
170   if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f);
171       foreach_elf_segment_flag;
172 #undef _
173     }
174
175   return s;
176 }
177
178 static u8 *
179 format_elf_symbol_binding_and_type (u8 * s, va_list * args)
180 {
181   int bt = va_arg (*args, int);
182   int b, t;
183   char *type_string = 0;
184   char *binding_string = 0;
185
186   switch ((b = ((bt >> 4) & 0xf)))
187     {
188 #define _(f,n) case n: binding_string = #f; break;
189       foreach_elf_symbol_binding;
190 #undef _
191     default:
192       break;
193     }
194
195   switch ((t = ((bt >> 0) & 0xf)))
196     {
197 #define _(f,n) case n: type_string = #f; break;
198       foreach_elf_symbol_type;
199 #undef _
200     default:
201       break;
202     }
203
204   if (binding_string)
205     s = format (s, "%s", binding_string);
206   else
207     s = format (s, "binding 0x%x", b);
208
209   if (type_string)
210     s = format (s, " %s", type_string);
211   else
212     s = format (s, " type 0x%x", t);
213
214   return s;
215 }
216
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;
226       foreach_elf_symbol_visibility
227 #undef _
228     }
229
230   if (t)
231     return format (s, "%s", t);
232   else
233     return format (s, "unknown 0x%x", visibility);
234 }
235
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
249   if (si >= ELF_SYMBOL_SECTION_RESERVED_LO
250       && si <= ELF_SYMBOL_SECTION_RESERVED_HI)
251     {
252       switch (si)
253         {
254 #define _(f,n) case n: t = #f; break;
255           foreach_elf_symbol_reserved_section_index
256 #undef _
257         default:
258           break;
259         }
260     }
261
262   if (t)
263     return format (s, "%s", t);
264   else
265     return format (s, "unknown 0x%x", si);
266 }
267
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[] = {
304           foreach_elf_x86_64_relocation_type
305         };
306
307 #undef _
308         if (type < ARRAY_LEN (tab))
309           t = tab[type];
310         break;
311       }
312
313     default:
314       break;
315     }
316
317   if (!t)
318     s = format (s, "0x%02x", type);
319   else
320     s = format (s, "%s", t);
321
322   return s;
323 }
324
325 static u8 *
326 format_elf_relocation (u8 * s, va_list * args)
327 {
328   elf_main_t *em = va_arg (*args, elf_main_t *);
329   elf_relocation_with_addend_t *r =
330     va_arg (*args, elf_relocation_with_addend_t *);
331   elf_symbol_table_t *t;
332   elf64_symbol_t *sym;
333
334   if (!r)
335     return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol");
336
337   t = vec_elt_at_index (em->symbol_tables, 0);
338   sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32);
339
340   s = format (s, "%16Lx%16U",
341               r->address,
342               format_elf_relocation_type, em, r->symbol_and_type & 0xff);
343
344   if (sym->section_index != 0)
345     {
346       elf_section_t *es;
347       es = vec_elt_at_index (em->sections, sym->section_index);
348       s = format (s, " (section %s)", elf_section_name (em, es));
349     }
350
351   if (sym->name != 0)
352     s = format (s, " %s", elf_symbol_name (t, sym));
353
354   {
355     i64 a = r->addend;
356     if (a != 0)
357       s = format (s, " %c 0x%Lx", a > 0 ? '+' : '-', a > 0 ? a : -a);
358   }
359
360   return s;
361 }
362
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;
371       foreach_elf_dynamic_entry_type;
372 #undef _
373     default:
374       break;
375     }
376   if (t)
377     return format (s, "%s", t);
378   else
379     return format (s, "unknown 0x%x", type);
380 }
381
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 =
413           elf_get_section_by_start_address_no_check (em, e->data);
414         if (es)
415           s = format (s, "section %s", elf_section_name (em, es));
416         else
417           s = format (s, "0x%Lx", e->data);
418         break;
419       }
420
421     default:
422       s = format (s, "0x%Lx", e->data);
423       break;
424     }
425
426   return s;
427 }
428
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;
438       foreach_elf_architecture;
439 #undef _
440     default:
441       return format (s, "unknown 0x%x", a);
442     }
443
444   return format (s, "%s", t);
445 }
446
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;
456       foreach_elf_abi;
457 #undef _
458     default:
459       return format (s, "unknown 0x%x", a);
460     }
461
462   return format (s, "%s", t);
463 }
464
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;
474       foreach_elf_file_class;
475 #undef _
476     default:
477       return format (s, "unknown 0x%x", a);
478     }
479
480   return format (s, "%s", t);
481 }
482
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;
498       foreach_elf_file_type;
499 #undef _
500     default:
501       return format (s, "unknown 0x%x", a);
502     }
503
504   return format (s, "%s", t);
505 }
506
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;
516       foreach_elf_data_encoding;
517 #undef _
518     default:
519       return format (s, "unknown 0x%x", a);
520     }
521
522   return format (s, "%s", t);
523 }
524
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",
554             format_elf_architecture, em->first_header.architecture,
555             format_elf_file_type, em->first_header.file_type,
556             format_elf_file_class, em->first_header.file_class,
557             format_elf_data_encoding, em->first_header.data_encoding,
558             format_elf_abi, em->first_header.abi,
559             em->first_header.abi_version);
560
561   s = format (s, "  entry 0x%Lx, arch-flags 0x%x",
562               em->file_header.entry_point, em->file_header.flags);
563
564   if (em->interpreter)
565     s = format (s, "\n  interpreter: %s", em->interpreter);
566
567   {
568     elf_section_t *h, *copy;
569
570     copy = 0;
571     vec_foreach (h, em->sections) if (h->header.type != ~0)
572       vec_add1 (copy, h[0]);
573
574     vec_sort_with_function (copy, elf_section_offset_compare);
575
576     s = format (s, "\nSections %d at file offset 0x%Lx-0x%Lx:\n",
577                 fh->section_header_count,
578                 fh->section_header_file_offset,
579                 fh->section_header_file_offset +
580                 (u64) fh->section_header_count * fh->section_header_size);
581     s = format (s, "%U\n", format_elf_section, em, 0);
582     vec_foreach (h, copy) s = format (s, "%U\n", format_elf_section, em, h);
583
584     vec_free (copy);
585   }
586
587   {
588     elf_segment_t *h, *copy;
589
590     copy = 0;
591     vec_foreach (h, em->segments)
592       if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
593       vec_add1 (copy, h[0]);
594
595     /* Sort segments by address. */
596     vec_sort_with_function (copy, elf_segment_va_compare);
597
598     s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n",
599                 fh->segment_header_count,
600                 fh->segment_header_file_offset,
601                 (u64) fh->segment_header_file_offset +
602                 (u64) fh->segment_header_count *
603                 (u64) fh->segment_header_size);
604
605     s = format (s, "%U\n", format_elf_segment, 0);
606     vec_foreach (h, copy) s = format (s, "%U\n", format_elf_segment, h);
607
608     vec_free (copy);
609   }
610
611   if ((verbose & FORMAT_ELF_MAIN_SYMBOLS) && vec_len (em->symbol_tables) > 0)
612     {
613       elf_symbol_table_t *t;
614       elf64_symbol_t *sym;
615       elf_section_t *es;
616
617       vec_foreach (t, em->symbol_tables)
618       {
619         es = vec_elt_at_index (em->sections, t->section_index);
620         s =
621           format (s, "\nSymbols for section %s:\n",
622                   elf_section_name (em, es));
623
624         s = format (s, "%U\n", format_elf_symbol, em, 0, 0);
625         vec_foreach (sym, t->symbols)
626           s = format (s, "%U\n", format_elf_symbol, em, t, sym);
627       }
628     }
629
630   if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
631       && vec_len (em->relocation_tables) > 0)
632     {
633       elf_relocation_table_t *t;
634       elf_relocation_with_addend_t *r;
635       elf_section_t *es;
636
637       vec_foreach (t, em->relocation_tables)
638       {
639         es = vec_elt_at_index (em->sections, t->section_index);
640         r = t->relocations;
641         s = format (s, "\nRelocations for section %s:\n",
642                     elf_section_name (em, es));
643
644         s = format (s, "%U\n", format_elf_relocation, em, 0);
645         vec_foreach (r, t->relocations)
646         {
647           s = format (s, "%U\n", format_elf_relocation, em, r);
648         }
649       }
650     }
651
652   if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
653       && vec_len (em->dynamic_entries) > 0)
654     {
655       elf64_dynamic_entry_t *es, *e;
656       s = format (s, "\nDynamic linker information:\n");
657       es = vec_dup (em->dynamic_entries);
658       s = format (s, "%U\n", format_elf_dynamic_entry, em, 0);
659       vec_foreach (e, es)
660         s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
661     }
662
663   return s;
664 }
665
666 static void
667 elf_parse_segments (elf_main_t * em, void *data)
668 {
669   void *d = data + em->file_header.segment_header_file_offset;
670   uword n = em->file_header.segment_header_count;
671   uword i;
672
673   vec_resize (em->segments, n);
674
675   for (i = 0; i < n; i++)
676     {
677       em->segments[i].index = i;
678
679       if (em->first_header.file_class == ELF_64BIT)
680         {
681           elf64_segment_header_t *h = d;
682 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
683           foreach_elf64_segment_header
684 #undef _
685             d = (h + 1);
686         }
687       else
688         {
689           elf32_segment_header_t *h = d;
690 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
691           foreach_elf32_segment_header
692 #undef _
693             d = (h + 1);
694         }
695     }
696 }
697
698 static void
699 elf_parse_sections (elf_main_t * em, void *data)
700 {
701   elf64_file_header_t *fh = &em->file_header;
702   elf_section_t *s;
703   void *d = data + fh->section_header_file_offset;
704   uword n = fh->section_header_count;
705   uword i;
706
707   vec_resize (em->sections, n);
708
709   for (i = 0; i < n; i++)
710     {
711       s = em->sections + i;
712
713       s->index = i;
714
715       if (em->first_header.file_class == ELF_64BIT)
716         {
717           elf64_section_header_t *h = d;
718 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
719           foreach_elf64_section_header
720 #undef _
721             d = (h + 1);
722         }
723       else
724         {
725           elf32_section_header_t *h = d;
726 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
727           foreach_elf32_section_header
728 #undef _
729             d = (h + 1);
730         }
731
732       if (s->header.type != ELF_SECTION_NO_BITS)
733         vec_add (s->contents, data + s->header.file_offset,
734                  s->header.file_size);
735     }
736
737   s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
738
739   em->section_by_name
740     = hash_create_string ( /* # elts */ vec_len (em->sections),
741                           /* sizeof of value */ sizeof (uword));
742
743   vec_foreach (s, em->sections)
744   {
745     hash_set_mem (em->section_by_name,
746                   elf_section_name (em, s), s - em->sections);
747     hash_set (em->section_by_start_address,
748               s->header.exec_address, s - em->sections);
749   }
750 }
751
752 static void
753 add_symbol_table (elf_main_t * em, elf_section_t * s)
754 {
755   elf_symbol_table_t *tab;
756   elf32_symbol_t *sym32;
757   elf64_symbol_t *sym64;
758   uword i;
759
760   if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
761     em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
762
763   vec_add2 (em->symbol_tables, tab, 1);
764
765   tab->section_index = s->index;
766
767   if (em->first_header.file_class == ELF_64BIT)
768     {
769       tab->symbols =
770         elf_get_section_contents (em, s - em->sections,
771                                   sizeof (tab->symbols[0]));
772       for (i = 0; i < vec_len (tab->symbols); i++)
773         {
774 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
775           foreach_elf64_symbol_header;
776 #undef _
777         }
778     }
779   else
780     {
781       sym32 =
782         elf_get_section_contents (em, s - em->sections, sizeof (sym32[0]));
783       vec_clone (tab->symbols, sym32);
784       for (i = 0; i < vec_len (tab->symbols); i++)
785         {
786 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
787           foreach_elf32_symbol_header;
788 #undef _
789         }
790     }
791
792   if (s->header.link == 0)
793     return;
794
795   tab->string_table =
796     elf_get_section_contents (em, s->header.link,
797                               sizeof (tab->string_table[0]));
798   tab->symbol_by_name =
799     hash_create_string ( /* # elts */ vec_len (tab->symbols),
800                         /* sizeof of value */ sizeof (uword));
801
802   vec_foreach (sym64, tab->symbols)
803   {
804     if (sym64->name != 0)
805       hash_set_mem (tab->symbol_by_name,
806                     tab->string_table + sym64->name, sym64 - tab->symbols);
807   }
808 }
809
810 static void
811 add_relocation_table (elf_main_t * em, elf_section_t * s)
812 {
813   uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
814   elf_relocation_table_t *t;
815   uword i;
816
817   vec_add2 (em->relocation_tables, t, 1);
818   t->section_index = s - em->sections;
819
820   if (em->first_header.file_class == ELF_64BIT)
821     {
822       elf64_relocation_t *r, *rs;
823
824       rs = elf_get_section_contents (em, t->section_index,
825                                      sizeof (rs[0]) +
826                                      has_addend * sizeof (rs->addend[0]));
827
828       if (em->need_byte_swap)
829         {
830           r = rs;
831           for (i = 0; i < vec_len (r); i++)
832             {
833               r->address = elf_swap_u64 (em, r->address);
834               r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
835               if (has_addend)
836                 r->addend[0] = elf_swap_u64 (em, r->addend[0]);
837               r = elf_relocation_next (r, s->header.type);
838             }
839         }
840
841       vec_resize (t->relocations, vec_len (rs));
842       clib_memcpy (t->relocations, rs, vec_bytes (t->relocations));
843       vec_free (rs);
844     }
845   else
846     {
847       elf_relocation_with_addend_t *r;
848       elf32_relocation_t *r32, *r32s;
849
850       r32s = elf_get_section_contents (em, t->section_index,
851                                        sizeof (r32s[0]) +
852                                        has_addend * sizeof (r32s->addend[0]));
853       vec_resize (t->relocations, vec_len (r32s));
854
855       r32 = r32s;
856       vec_foreach (r, t->relocations)
857       {
858         r->address = elf_swap_u32 (em, r32->address);
859         r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
860         r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0;
861         r32 = elf_relocation_next (r32, s->header.type);
862       }
863
864       vec_free (r32s);
865     }
866 }
867
868 void
869 elf_parse_symbols (elf_main_t * em)
870 {
871   elf_section_t *s;
872
873   /* No need to parse symbols twice. */
874   if (em->parsed_symbols)
875     return;
876   em->parsed_symbols = 1;
877
878   vec_foreach (s, em->sections)
879   {
880     switch (s->header.type)
881       {
882       case ELF_SECTION_SYMBOL_TABLE:
883       case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
884         add_symbol_table (em, s);
885         break;
886
887       case ELF_SECTION_RELOCATION_ADD:
888       case ELF_SECTION_RELOCATION:
889         add_relocation_table (em, s);
890         break;
891
892       default:
893         break;
894       }
895   }
896 }
897
898 void
899 elf_set_dynamic_entries (elf_main_t * em)
900 {
901   uword i;
902
903   /* Start address for sections may have changed. */
904   {
905     elf64_dynamic_entry_t *e;
906
907     vec_foreach (e, em->dynamic_entries)
908     {
909       switch (e->type)
910         {
911         case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
912         case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
913         case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
914         case ELF_DYNAMIC_ENTRY_GNU_HASH:
915         case ELF_DYNAMIC_ENTRY_STRING_TABLE:
916         case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
917         case ELF_DYNAMIC_ENTRY_PLT_GOT:
918         case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
919         case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
920         case ELF_DYNAMIC_ENTRY_VERSION_NEED:
921         case ELF_DYNAMIC_ENTRY_VERSYM:
922           {
923             elf_section_t *es =
924               elf_get_section_by_start_address_no_check (em, e->data);
925             /* If section is not found just leave e->data alone. */
926             if (es)
927               e->data = es->header.exec_address;
928             break;
929           }
930
931         default:
932           break;
933         }
934     }
935   }
936
937   if (em->first_header.file_class == ELF_64BIT)
938     {
939       elf64_dynamic_entry_t *e, *es;
940
941       es = em->dynamic_entries;
942       if (em->need_byte_swap)
943         {
944           es = vec_dup (es);
945           vec_foreach (e, es)
946           {
947             e->type = elf_swap_u64 (em, e->type);
948             e->data = elf_swap_u64 (em, e->data);
949           }
950         }
951
952       elf_set_section_contents (em, em->dynamic_section_index, es,
953                                 vec_bytes (es));
954       if (es != em->dynamic_entries)
955         vec_free (es);
956     }
957   else
958     {
959       elf32_dynamic_entry_t *es;
960
961       vec_clone (es, em->dynamic_entries);
962       if (em->need_byte_swap)
963         {
964           for (i = 0; i < vec_len (es); i++)
965             {
966               es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type);
967               es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data);
968             }
969         }
970
971       elf_set_section_contents (em, em->dynamic_section_index, es,
972                                 vec_bytes (es));
973       vec_free (es);
974     }
975 }
976
977 clib_error_t *
978 elf_parse (elf_main_t * em, void *data, uword data_bytes)
979 {
980   elf_first_header_t *h = data;
981   elf64_file_header_t *fh = &em->file_header;
982   clib_error_t *error = 0;
983
984   {
985     char *save = em->file_name;
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 =
992     CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding ==
993                                 ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
994   elf_swap_first_header (em, &em->first_header);
995
996   if (!(h->magic[0] == 0x7f
997         && h->magic[1] == 'E' && h->magic[2] == 'L' && h->magic[3] == 'F'))
998     return clib_error_return (0, "`%s': bad magic", em->file_name);
999
1000   if (h->file_class == ELF_64BIT)
1001     {
1002       elf64_file_header_t *h64 = (void *) (h + 1);
1003 #define _(t,f) fh->f = elf_swap_##t (em, h64->f);
1004       foreach_elf64_file_header
1005 #undef _
1006     }
1007   else
1008     {
1009       elf32_file_header_t *h32 = (void *) (h + 1);
1010
1011 #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
1012       foreach_elf32_file_header
1013 #undef _
1014     }
1015
1016   elf_parse_segments (em, data);
1017   elf_parse_sections (em, data);
1018
1019   /* Figure which sections are contained in each segment. */
1020   {
1021     elf_segment_t *g;
1022     elf_section_t *s;
1023     vec_foreach (g, em->segments)
1024     {
1025       u64 g_lo, g_hi;
1026       u64 s_lo, s_hi;
1027
1028       if (g->header.memory_size == 0)
1029         continue;
1030
1031       g_lo = g->header.virtual_address;
1032       g_hi = g_lo + g->header.memory_size;
1033
1034       vec_foreach (s, em->sections)
1035       {
1036         s_lo = s->header.exec_address;
1037         s_hi = s_lo + s->header.file_size;
1038
1039         if (s_lo >= g_lo && s_hi <= g_hi)
1040           {
1041             g->section_index_bitmap =
1042               clib_bitmap_ori (g->section_index_bitmap, s->index);
1043             s->segment_index_bitmap =
1044               clib_bitmap_ori (s->segment_index_bitmap, g->index);
1045           }
1046       }
1047     }
1048   }
1049
1050   return error;
1051 }
1052
1053 #ifdef CLIB_UNIX
1054
1055 static void
1056 add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1057 {
1058   uword i;
1059
1060   /* Can't have more than one dynamic section. */
1061   ASSERT (em->dynamic_section_index == 0);
1062   em->dynamic_section_index = s->index;
1063
1064   if (em->first_header.file_class == ELF_64BIT)
1065     {
1066       elf64_dynamic_entry_t *e;
1067
1068       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1069       if (em->need_byte_swap)
1070         for (i = 0; i < vec_len (e); i++)
1071           {
1072             e[i].type = elf_swap_u64 (em, e[i].type);
1073             e[i].data = elf_swap_u64 (em, e[i].data);
1074           }
1075
1076       em->dynamic_entries = e;
1077     }
1078   else
1079     {
1080       elf32_dynamic_entry_t *e;
1081
1082       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1083       vec_clone (em->dynamic_entries, e);
1084       if (em->need_byte_swap)
1085         for (i = 0; i < vec_len (e); i++)
1086           {
1087             em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type);
1088             em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data);
1089           }
1090
1091       vec_free (e);
1092     }
1093 }
1094
1095 static void
1096 byte_swap_verneed (elf_main_t * em, elf_dynamic_version_need_union_t * vus)
1097 {
1098   uword *entries_swapped = 0;
1099   uword i, j;
1100
1101   for (i = 0; i < vec_len (vus); i++)
1102     {
1103       elf_dynamic_version_need_union_t *n = vec_elt_at_index (vus, i);
1104       elf_dynamic_version_need_union_t *a;
1105
1106       if (clib_bitmap_get (entries_swapped, i))
1107         continue;
1108
1109       elf_swap_verneed (&n->need);
1110       entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1111
1112       if (n->need.first_aux_offset != 0)
1113         {
1114           ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1115           j = i + (n->need.first_aux_offset / sizeof (n[0]));
1116           while (1)
1117             {
1118               a = vec_elt_at_index (vus, j);
1119               if (!clib_bitmap_get (entries_swapped, j))
1120                 {
1121                   entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1122                   elf_swap_verneed_aux (&a->aux);
1123                 }
1124               if (a->aux.next_offset == 0)
1125                 break;
1126               ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1127               j += (a->aux.next_offset / sizeof (a->aux));
1128             }
1129         }
1130     }
1131
1132   clib_bitmap_free (entries_swapped);
1133 }
1134
1135 static void set_dynamic_verneed (elf_main_t * em) __attribute__ ((unused));
1136 static void
1137 set_dynamic_verneed (elf_main_t * em)
1138 {
1139   elf_dynamic_version_need_union_t *vus = em->verneed;
1140
1141   if (em->need_byte_swap)
1142     {
1143       vus = vec_dup (vus);
1144       byte_swap_verneed (em, vus);
1145     }
1146
1147   elf_set_section_contents (em, em->verneed_section_index, vus,
1148                             vec_bytes (vus));
1149   if (vus != em->verneed)
1150     vec_free (vus);
1151 }
1152
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);
1168         foreach_elf64_symbol_header;
1169 #undef _
1170       }
1171
1172       elf_set_section_contents (em, tab->section_index,
1173                                 syms, vec_bytes (syms));
1174     }
1175   else
1176     {
1177       elf32_symbol_t *syms;
1178       uword i;
1179       vec_clone (syms, tab->symbols);
1180       for (i = 0; i < vec_len (tab->symbols); i++)
1181         {
1182 #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1183           foreach_elf32_symbol_header;
1184 #undef _
1185         }
1186
1187       elf_set_section_contents (em, tab->section_index,
1188                                 syms, vec_bytes (syms));
1189     }
1190 }
1191
1192 static char *
1193 elf_find_interpreter (elf_main_t * em, void *data)
1194 {
1195   elf_segment_t *g;
1196   elf_section_t *s;
1197   uword *p;
1198
1199   vec_foreach (g, em->segments)
1200   {
1201     if (g->header.type == ELF_SEGMENT_INTERP)
1202       break;
1203   }
1204
1205   if (g >= vec_end (em->segments))
1206     return 0;
1207
1208   p = hash_get (em->section_by_start_address, g->header.virtual_address);
1209   if (!p)
1210     return 0;
1211
1212   s = vec_elt_at_index (em->sections, p[0]);
1213   return (char *) vec_dup (s->contents);
1214 }
1215
1216 static void *
1217 elf_get_section_contents_with_starting_address (elf_main_t * em,
1218                                                 uword start_address,
1219                                                 uword elt_size,
1220                                                 u32 * section_index_result)
1221 {
1222   elf_section_t *s = 0;
1223   clib_error_t *error;
1224
1225   error = elf_get_section_by_start_address (em, start_address, &s);
1226   if (error)
1227     {
1228       clib_error_report (error);
1229       return 0;
1230     }
1231
1232   if (section_index_result)
1233     *section_index_result = s->index;
1234
1235   return elf_get_section_contents (em, s->index, elt_size);
1236 }
1237
1238 static void
1239 elf_parse_dynamic (elf_main_t * em)
1240 {
1241   elf_section_t *s;
1242   elf64_dynamic_entry_t *e;
1243
1244   vec_foreach (s, em->sections)
1245   {
1246     switch (s->header.type)
1247       {
1248       case ELF_SECTION_DYNAMIC:
1249         add_dynamic_entries (em, s);
1250         break;
1251
1252       default:
1253         break;
1254       }
1255   }
1256
1257   em->dynamic_string_table_section_index = ~0;
1258   em->dynamic_string_table = 0;
1259
1260   vec_foreach (e, em->dynamic_entries)
1261   {
1262     switch (e->type)
1263       {
1264       case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1265         ASSERT (vec_len (em->dynamic_string_table) == 0);
1266         em->dynamic_string_table
1267           =
1268           elf_get_section_contents_with_starting_address (em, e->data,
1269                                                           sizeof (u8),
1270                                                           &em->
1271                                                           dynamic_string_table_section_index);
1272         break;
1273
1274       case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1275         {
1276           elf_section_t *s = 0;
1277           clib_error_t *error;
1278
1279           error = elf_get_section_by_start_address (em, e->data, &s);
1280           if (error)
1281             {
1282               clib_error_report (error);
1283               return;
1284             }
1285
1286           em->dynamic_symbol_table_section_index = s - em->sections;
1287         }
1288         break;
1289
1290       case ELF_DYNAMIC_ENTRY_VERSYM:
1291         em->versym
1292           =
1293           elf_get_section_contents_with_starting_address (em, e->data,
1294                                                           sizeof (em->versym
1295                                                                   [0]),
1296                                                           &em->
1297                                                           versym_section_index);
1298         if (em->need_byte_swap)
1299           {
1300             uword i;
1301             for (i = 0; i < vec_len (em->versym); i++)
1302               em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1303           }
1304         break;
1305
1306       case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1307         em->verneed
1308           =
1309           elf_get_section_contents_with_starting_address (em, e->data,
1310                                                           sizeof (em->verneed
1311                                                                   [0]),
1312                                                           &em->
1313                                                           verneed_section_index);
1314         if (em->need_byte_swap)
1315           byte_swap_verneed (em, em->verneed);
1316         break;
1317
1318       default:
1319         break;
1320       }
1321   }
1322 }
1323
1324 #include <sys/types.h>
1325 #include <sys/stat.h>
1326 #include <fcntl.h>
1327
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 {
1389   u8 *new_table;
1390
1391   u8 *old_table;
1392
1393   uword *hash;
1394 } string_table_builder_t;
1395
1396 static u32
1397 string_table_add_name (string_table_builder_t * b, u8 * n)
1398 {
1399   uword *p, i, j, l;
1400
1401   p = hash_get_mem (b->hash, n);
1402   if (p)
1403     return p[0];
1404
1405   l = strlen ((char *) n);
1406   i = vec_len (b->new_table);
1407   vec_add (b->new_table, n, l + 1);
1408
1409   for (j = 0; j <= l; j++)
1410     {
1411       if (j > 0)
1412         {
1413           p = hash_get_mem (b->hash, n + j);
1414
1415           /* Sub-string already in table? */
1416           if (p)
1417             continue;
1418         }
1419
1420       hash_set_mem (b->hash, n + j, i + j);
1421     }
1422
1423   return i;
1424 }
1425
1426 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1427   __attribute__ ((unused));
1428 static u32
1429 string_table_add_name_index (string_table_builder_t * b, u32 index)
1430 {
1431   u8 *n = b->old_table + index;
1432   return string_table_add_name (b, n);
1433 }
1434
1435 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1436   __attribute__ ((unused));
1437 static void
1438 string_table_init (string_table_builder_t * b, u8 * old_table)
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
1445 static u8 *string_table_done (string_table_builder_t * b)
1446   __attribute__ ((unused));
1447 static u8 *
1448 string_table_done (string_table_builder_t * b)
1449 {
1450   hash_free (b->hash);
1451   return b->new_table;
1452 }
1453
1454 static void
1455 layout_sections (elf_main_t * em)
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 =
1481         vec_elt_at_index (em->sections,
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     {
1491       string_table_builder_t b;
1492
1493       string_table_init (&b, em->dynamic_string_table);
1494
1495       /* Add all dynamic symbols. */
1496       {
1497         elf_symbol_table_t *symtab;
1498         elf64_symbol_t *sym;
1499
1500         symtab =
1501           vec_elt_at_index (em->symbol_tables,
1502                             em->dynamic_symbol_table_index);
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
1509         set_symbol_table (em, em->dynamic_symbol_table_index);
1510       }
1511
1512       /* Add all dynamic entries. */
1513       {
1514         elf64_dynamic_entry_t *e;
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         {
1532           elf_dynamic_version_need_union_t *n, *a;
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 =
1563         vec_elt_at_index (em->sections,
1564                           em->dynamic_string_table_section_index);
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:
1588           if (!(s->index == em->dynamic_string_table_section_index
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 =
1672             vec_elt_at_index (em->sections,
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)
1690     elf_set_dynamic_entries (em);
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* */
1708         clib_bitmap_foreach (si, g->section_index_bitmap, ({
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   {
1772     elf_first_header_t h = em->first_header;
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   {
1784     elf64_file_header_t h = em->file_header;
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);
1796         foreach_elf64_file_header;
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);
1810         foreach_elf32_file_header;
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     {
1827       elf64_segment_header_t h;
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);
1837           foreach_elf64_segment_header;
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         {
1850           elf32_segment_header_t h32;
1851
1852 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1853           foreach_elf32_segment_header;
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     {
1904       elf64_section_header_t h;
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);
1914           foreach_elf64_section_header;
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         {
1927           elf32_section_header_t h32;
1928
1929 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1930           foreach_elf32_section_header;
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
1965 elf_create_section_with_contents (elf_main_t * em,
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 =
1991     vec_elt_at_index (em->sections,
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
2016 elf_delete_segment_with_type (elf_main_t * em,
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  */