63c17ec382e1a9ab9acc4121f2a7c712bf5a6095
[vpp.git] / vppinfra / 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, elf_section_t ** result)
48 {
49   uword * p;
50
51   p = hash_get_mem (em->section_by_name, section_name);
52   if (! p)
53     return clib_error_return (0, "no such section `%s'", section_name);
54
55   *result = vec_elt_at_index (em->sections, p[0]);
56   return 0;
57 }
58
59 elf_section_t *
60 elf_get_section_by_start_address_no_check (elf_main_t * em, uword start_address)
61 {
62   uword * p = hash_get (em->section_by_start_address, start_address);
63   return p ? vec_elt_at_index (em->sections, p[0]) : 0;
64 }
65
66 clib_error_t *
67 elf_get_section_by_start_address (elf_main_t * em, uword start_address, elf_section_t ** result)
68 {
69   elf_section_t * s = elf_get_section_by_start_address_no_check (em, start_address);
70   if (! s)
71     return clib_error_return (0, "no section with address 0x%wx", start_address);
72   *result = s;
73   return 0;
74 }
75
76 static u8 *
77 format_elf_section_type (u8 * s, va_list * args)
78 {
79   elf_section_type_t type = va_arg (*args, elf_section_type_t);
80   char * t = 0;
81
82   switch (type)
83     {
84 #define _(f,i) case ELF_SECTION_##f: t = #f; break;
85       foreach_elf_section_type
86 #undef _
87     }
88
89   if (! t)
90     s = format (s, "unknown 0x%x", type);
91   else
92     s = format (s, "%s", t);
93   return s;
94 }
95
96 static u8 *
97 format_elf_section (u8 * s, va_list * args)
98 {
99   elf_main_t * em = va_arg (*args, elf_main_t *);
100   elf_section_t * es = va_arg (*args, elf_section_t *);
101   elf64_section_header_t * h = &es->header;
102
103   if (! h)
104     return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s",
105                    "Name", "Index", "Type", "Size", "Align", "Address", "File offset");
106
107   s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx",
108               elf_section_name (em, es),
109               es->index,
110               format_elf_section_type, h->type,
111               h->file_size,
112               h->align,
113               h->exec_address,
114               h->file_offset, h->file_offset + h->file_size);
115
116   if (h->flags != 0)
117     {
118 #define _(f,i) \
119   if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f);
120       foreach_elf_section_flag;
121 #undef _
122     }
123
124   return s;
125 }
126
127 static u8 *
128 format_elf_segment_type (u8 * s, va_list * args)
129 {
130   elf_segment_type_t type = va_arg (*args, elf_segment_type_t);
131   char * t = 0;
132
133   switch (type)
134     {
135 #define _(f,i) case ELF_SEGMENT_##f: t = #f; break;
136       foreach_elf_segment_type
137 #undef _
138     }
139
140   if (! t)
141     s = format (s, "unknown 0x%x", type);
142   else
143     s = format (s, "%s", t);
144   return s;
145 }
146
147 static u8 *
148 format_elf_segment (u8 * s, va_list * args)
149 {
150   elf_segment_t * es = va_arg (*args, elf_segment_t *);
151   elf64_segment_header_t * h = &es->header;
152
153   if (! h)
154     return format (s, "%=16s%=16s%=16s%=16s",
155                    "Type", "Virt. Address", "Phys. Address", "Size");
156
157   s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx",
158               format_elf_segment_type, h->type,
159               h->virtual_address,
160               h->physical_address,
161               h->memory_size,
162               h->file_offset);
163
164   if (h->flags != 0)
165     {
166 #define _(f,i) \
167   if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f);
168       foreach_elf_segment_flag;
169 #undef _
170     }
171
172   return s;
173 }
174
175 static u8 *
176 format_elf_symbol_binding_and_type (u8 * s, va_list * args)
177 {
178   int bt = va_arg (*args, int);
179   int b, t;
180   char * type_string = 0;
181   char * binding_string = 0;
182   
183   switch ((b = ((bt >> 4) & 0xf)))
184     {
185 #define _(f,n) case n: binding_string = #f; break;
186       foreach_elf_symbol_binding;
187 #undef _
188     default: break;
189     }
190
191   switch ((t = ((bt >> 0) & 0xf)))
192     {
193 #define _(f,n) case n: type_string = #f; break;
194       foreach_elf_symbol_type;
195 #undef _
196     default: break;
197     }
198
199   if (binding_string)
200     s = format (s, "%s", binding_string);
201   else
202     s = format (s, "binding 0x%x", b);
203
204   if (type_string)
205     s = format (s, " %s", type_string);
206   else
207     s = format (s, " type 0x%x", t);
208
209   return s;
210 }
211
212 static u8 *
213 format_elf_symbol_visibility (u8 * s, va_list * args)
214 {
215   int visibility = va_arg (*args, int);
216   char * t = 0;
217
218   switch (visibility)
219     {
220 #define _(f,n) case n: t = #f; break;
221       foreach_elf_symbol_visibility
222 #undef _
223     }
224
225   if (t)
226     return format (s, "%s", t);
227   else
228     return format (s, "unknown 0x%x", visibility);
229 }
230
231 static u8 *
232 format_elf_symbol_section_name (u8 * s, va_list * args)
233 {
234   elf_main_t * em = va_arg (*args, elf_main_t *);
235   int si = va_arg (*args, int);
236   char * t = 0;
237
238   if (si < vec_len (em->sections))
239     {
240       elf_section_t * es = vec_elt_at_index (em->sections, si);
241       return format (s, "%s", elf_section_name (em, es));
242     }
243
244   if (si >= ELF_SYMBOL_SECTION_RESERVED_LO
245       && si <= ELF_SYMBOL_SECTION_RESERVED_HI)
246     {
247       switch (si)
248         {
249 #define _(f,n) case n: t = #f; break;
250           foreach_elf_symbol_reserved_section_index
251 #undef _
252         default:
253           break;
254         }
255     }
256
257   if (t)
258     return format (s, "%s", t);
259   else
260     return format (s, "unknown 0x%x", si);
261 }
262
263 u8 * format_elf_symbol (u8 * s, va_list * args)
264 {
265   elf_main_t * em = va_arg (*args, elf_main_t *);
266   elf_symbol_table_t * t = va_arg (*args, elf_symbol_table_t *);
267   elf64_symbol_t * sym = va_arg (*args, elf64_symbol_t *);
268
269   if (! sym)
270     return format (s, "%=32s%=16s%=16s%=16s%=16s%=16s",
271                    "Symbol", "Size", "Value", "Type", "Visibility", "Section");
272
273   s = format (s, "%-32s%16Ld%16Lx%=16U%=16U%U",
274               elf_symbol_name (t, sym),
275               sym->size, sym->value,
276               format_elf_symbol_binding_and_type, sym->binding_and_type,
277               format_elf_symbol_visibility, sym->visibility,
278               format_elf_symbol_section_name, em, sym->section_index);
279
280   return s;
281 }
282
283 static u8 *
284 format_elf_relocation_type (u8 * s, va_list * args)
285 {
286   elf_main_t * em = va_arg (*args, elf_main_t *);
287   int type = va_arg (*args, int);
288   char * t = 0;
289
290   switch (em->first_header.architecture)
291     {
292 #define _(f,i) [i] = #f,
293
294     case ELF_ARCH_X86_64:
295       {
296         static char * tab[] = {
297           foreach_elf_x86_64_relocation_type
298         };
299
300 #undef _
301         if (type < ARRAY_LEN (tab))
302           t = tab[type];
303         break;
304       }
305
306     default:
307       break;
308     }
309
310   if (! t)
311     s = format (s, "0x%02x", type);
312   else
313     s = format (s, "%s", t);
314
315   return s;
316 }
317
318 static u8 *
319 format_elf_relocation (u8 * s, va_list * args)
320 {
321   elf_main_t * em = va_arg (*args, elf_main_t *);
322   elf_relocation_with_addend_t * r = va_arg (*args, elf_relocation_with_addend_t *);
323   elf_symbol_table_t * t;
324   elf64_symbol_t * sym;
325
326   if (! r)
327     return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol");
328
329   t = vec_elt_at_index (em->symbol_tables, 0);
330   sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32);
331
332   s = format (s, "%16Lx%16U",
333               r->address,
334               format_elf_relocation_type, em, r->symbol_and_type & 0xff);
335
336   if (sym->section_index != 0)
337     {
338       elf_section_t * es;
339       es = vec_elt_at_index (em->sections, sym->section_index);
340       s = format (s, " (section %s)", elf_section_name (em, es));
341     }
342
343   if (sym->name != 0)
344     s = format (s, " %s", elf_symbol_name (t, sym));
345
346   {
347     i64 a = r->addend;
348     if (a != 0)
349       s = format (s, " %c 0x%Lx",
350                   a > 0 ? '+' : '-',
351                   a > 0 ? a : -a);
352   }
353
354   return s;
355 }
356
357 static u8 *
358 format_elf_dynamic_entry_type (u8 * s, va_list * args)
359 {
360   u32 type = va_arg (*args, u32);
361   char * t = 0;
362   switch (type)
363     {
364 #define _(f,n) case n: t = #f; break;
365       foreach_elf_dynamic_entry_type;
366 #undef _
367     default: break;
368     }
369   if (t)
370     return format (s, "%s", t);
371   else
372     return format (s, "unknown 0x%x", type);
373 }
374
375 static u8 *
376 format_elf_dynamic_entry (u8 * s, va_list * args)
377 {
378   elf_main_t * em = va_arg (*args, elf_main_t *);
379   elf64_dynamic_entry_t * e = va_arg (*args, elf64_dynamic_entry_t *);
380
381   if (! e)
382     return format (s, "%=40s%=16s", "Type", "Data");
383
384   s = format (s, "%=40U",
385               format_elf_dynamic_entry_type, (u32) e->type);
386   switch (e->type)
387     {
388     case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
389     case ELF_DYNAMIC_ENTRY_RPATH:
390     case ELF_DYNAMIC_ENTRY_RUN_PATH:
391       s = format (s, "%s", em->dynamic_string_table + e->data);
392       break;
393
394     case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
395     case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
396     case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
397     case ELF_DYNAMIC_ENTRY_GNU_HASH:
398     case ELF_DYNAMIC_ENTRY_STRING_TABLE:
399     case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
400     case ELF_DYNAMIC_ENTRY_PLT_GOT:
401     case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
402     case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
403     case ELF_DYNAMIC_ENTRY_VERSION_NEED:
404     case ELF_DYNAMIC_ENTRY_VERSYM:
405       {
406         elf_section_t * es = elf_get_section_by_start_address_no_check (em, e->data);
407         if (es)
408           s = format (s, "section %s", elf_section_name (em, es));
409         else
410           s = format (s, "0x%Lx", e->data);
411         break;
412       }
413
414     default:
415       s = format (s, "0x%Lx", e->data);
416       break;
417     }
418
419   return s;
420 }
421
422 static u8 * format_elf_architecture (u8 * s, va_list * args)
423 {
424   int a = va_arg (*args, int);
425   char * t;
426
427   switch (a)
428     {
429 #define _(f,n) case n: t = #f; break;
430       foreach_elf_architecture;
431 #undef _
432     default:
433       return format (s, "unknown 0x%x", a);
434     }
435
436   return format (s, "%s", t);
437 }
438
439 static u8 * format_elf_abi (u8 * s, va_list * args)
440 {
441   int a = va_arg (*args, int);
442   char * t;
443
444   switch (a)
445     {
446 #define _(f,n) case n: t = #f; break;
447       foreach_elf_abi;
448 #undef _
449     default:
450       return format (s, "unknown 0x%x", a);
451     }
452
453   return format (s, "%s", t);
454 }
455
456 static u8 * format_elf_file_class (u8 * s, va_list * args)
457 {
458   int a = va_arg (*args, int);
459   char * t;
460
461   switch (a)
462     {
463 #define _(f) case ELF_##f: t = #f; break;
464       foreach_elf_file_class;
465 #undef _
466     default:
467       return format (s, "unknown 0x%x", a);
468     }
469
470   return format (s, "%s", t);
471 }
472
473 static u8 * format_elf_file_type (u8 * s, va_list * args)
474 {
475   int a = va_arg (*args, int);
476   char * t;
477
478   if (a >= ELF_ARCH_SPECIFIC_LO && a <= ELF_ARCH_SPECIFIC_HI)
479     return format (s, "arch-specific 0x%x", a - ELF_ARCH_SPECIFIC_LO);
480
481   if (a >= ELF_OS_SPECIFIC_LO && a <= ELF_OS_SPECIFIC_HI)
482     return format (s, "os-specific 0x%x", a - ELF_OS_SPECIFIC_LO);
483
484   switch (a)
485     {
486 #define _(f,n) case n: t = #f; break;
487       foreach_elf_file_type;
488 #undef _
489     default:
490       return format (s, "unknown 0x%x", a);
491     }
492
493   return format (s, "%s", t);
494 }
495
496 static u8 * format_elf_data_encoding (u8 * s, va_list * args)
497 {
498   int a = va_arg (*args, int);
499   char * t;
500
501   switch (a)
502     {
503 #define _(f) case ELF_##f: t = #f; break;
504       foreach_elf_data_encoding;
505 #undef _
506     default:
507       return format (s, "unknown 0x%x", a);
508     }
509
510   return format (s, "%s", t);
511 }
512
513 static int elf_section_offset_compare (void *a1, void *a2)
514 {
515   elf_section_t *s1 = a1;
516   elf_section_t *s2 = a2;
517   
518   return ((i64)s1->header.file_offset - (i64)s2->header.file_offset);
519 }
520
521 static int elf_segment_va_compare (void *a1, void *a2)
522 {
523   elf_segment_t *s1 = a1;
524   elf_segment_t *s2 = a2;
525   
526   return ((i64)s1->header.virtual_address - (i64)s2->header.virtual_address);
527 }
528
529 u8 *
530 format_elf_main (u8 * s, va_list * args)
531 {
532   elf_main_t * em = va_arg (*args, elf_main_t *);
533   u32 verbose = va_arg (*args, u32);
534   elf64_file_header_t * fh = &em->file_header;
535
536   s = format (s, "File header: machine: %U, file type/class %U/%U, data-encoding: %U, abi: %U version %d\n",
537               format_elf_architecture, em->first_header.architecture,
538               format_elf_file_type, em->first_header.file_type,
539               format_elf_file_class, em->first_header.file_class,
540               format_elf_data_encoding, em->first_header.data_encoding,
541               format_elf_abi, em->first_header.abi, em->first_header.abi_version);
542
543   s = format (s, "  entry 0x%Lx, arch-flags 0x%x",
544               em->file_header.entry_point, em->file_header.flags);
545
546   if (em->interpreter)
547     s = format (s, "\n  interpreter: %s", em->interpreter);
548
549   {
550     elf_section_t * h, * copy;
551
552     copy = 0;
553     vec_foreach (h, em->sections)
554       if (h->header.type != ~0)
555         vec_add1 (copy, h[0]);
556
557     vec_sort_with_function (copy, elf_section_offset_compare);
558
559     s = format (s, "\nSections %d at file offset 0x%Lx-0x%Lx:\n",
560                 fh->section_header_count,
561                 fh->section_header_file_offset,
562                 fh->section_header_file_offset + 
563                 (u64) fh->section_header_count * fh->section_header_size);
564     s = format (s, "%U\n", format_elf_section, em, 0);
565     vec_foreach (h, copy)
566       s = format (s, "%U\n", format_elf_section, em, h);
567
568     vec_free (copy);
569   }
570
571   {
572     elf_segment_t * h, * copy;
573
574     copy = 0;
575     vec_foreach (h, em->segments)
576       if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
577         vec_add1 (copy, h[0]);
578
579     /* Sort segments by address. */
580     vec_sort_with_function (copy, elf_segment_va_compare);
581
582     s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n",
583                 fh->segment_header_count,
584                 fh->segment_header_file_offset,
585                 (u64) fh->segment_header_file_offset + (u64) fh->segment_header_count * (u64) fh->segment_header_size);
586                 
587     s = format (s, "%U\n", format_elf_segment, 0);
588     vec_foreach (h, copy)
589       s = format (s, "%U\n", format_elf_segment, h);
590
591     vec_free (copy);
592   }
593
594   if ((verbose & FORMAT_ELF_MAIN_SYMBOLS)
595       && vec_len (em->symbol_tables) > 0)
596     {
597       elf_symbol_table_t * t;
598       elf64_symbol_t * sym;
599       elf_section_t * es;
600
601       vec_foreach (t, em->symbol_tables)
602         {
603           es = vec_elt_at_index (em->sections, t->section_index);
604           s = format (s, "\nSymbols for section %s:\n", elf_section_name (em, es));
605
606           s = format (s, "%U\n", format_elf_symbol, em, 0, 0);
607           vec_foreach (sym, t->symbols)
608             s = format (s, "%U\n", format_elf_symbol, em, t, sym);
609         }
610     }
611
612   if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
613       && vec_len (em->relocation_tables) > 0)
614     {
615       elf_relocation_table_t * t;
616       elf_relocation_with_addend_t * r;
617       elf_section_t * es;
618
619       vec_foreach (t, em->relocation_tables)
620         {
621           es = vec_elt_at_index (em->sections, t->section_index);
622           r = t->relocations;
623           s = format (s, "\nRelocations for section %s:\n",
624                       elf_section_name (em, es));
625
626           s = format (s, "%U\n", format_elf_relocation, em, 0);
627           vec_foreach (r, t->relocations)
628             {
629               s = format (s, "%U\n",
630                           format_elf_relocation, em, r);
631             }
632         }
633     }
634
635   if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
636       && vec_len (em->dynamic_entries) > 0)
637     {
638       elf64_dynamic_entry_t * es, * e;
639       s = format (s, "\nDynamic linker information:\n");
640       es = vec_dup (em->dynamic_entries);
641       s = format (s, "%U\n", format_elf_dynamic_entry, em, 0);
642       vec_foreach (e, es)
643         s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
644     }
645
646   return s;
647 }
648
649 static void
650 elf_parse_segments (elf_main_t * em, void * data)
651 {
652   void * d = data + em->file_header.segment_header_file_offset;
653   uword n = em->file_header.segment_header_count;
654   uword i;
655
656   vec_resize (em->segments, n);
657
658   for (i = 0; i < n; i++)
659     {
660       em->segments[i].index = i;
661
662       if (em->first_header.file_class == ELF_64BIT)
663         {
664           elf64_segment_header_t * h = d;
665 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
666           foreach_elf64_segment_header
667 #undef _
668           d = (h + 1);
669         }
670       else
671         {
672           elf32_segment_header_t * h = d;
673 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
674           foreach_elf32_segment_header
675 #undef _
676           d = (h + 1);
677         }
678     }
679 }
680
681 static void
682 elf_parse_sections (elf_main_t * em, void * data)
683 {
684   elf64_file_header_t * fh = &em->file_header;
685   elf_section_t * s;
686   void * d = data + fh->section_header_file_offset;
687   uword n = fh->section_header_count;
688   uword i;
689
690   vec_resize (em->sections, n);
691
692   for (i = 0; i < n; i++)
693     {
694       s = em->sections + i;
695
696       s->index = i;
697
698       if (em->first_header.file_class == ELF_64BIT)
699         {
700           elf64_section_header_t * h = d;
701 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
702           foreach_elf64_section_header
703 #undef _
704           d = (h + 1);
705         }
706       else
707         {
708           elf32_section_header_t * h = d;
709 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
710           foreach_elf32_section_header
711 #undef _
712           d = (h + 1);
713         }
714
715       if (s->header.type != ELF_SECTION_NO_BITS)
716         vec_add (s->contents, data + s->header.file_offset, s->header.file_size);
717     }
718
719   s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
720
721   em->section_by_name
722     = hash_create_string (/* # elts */ vec_len (em->sections),
723                           /* sizeof of value */ sizeof (uword));
724
725   vec_foreach (s, em->sections)
726     {
727       hash_set_mem (em->section_by_name,
728                     elf_section_name (em, s),
729                     s - em->sections);
730       hash_set (em->section_by_start_address,
731                 s->header.exec_address,
732                 s - em->sections);
733     }
734 }
735
736 static void
737 add_symbol_table (elf_main_t * em, elf_section_t * s)
738 {
739   elf_symbol_table_t * tab;
740   elf32_symbol_t * sym32;
741   elf64_symbol_t * sym64;
742   uword i;
743
744   if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
745     em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
746
747   vec_add2 (em->symbol_tables, tab, 1);
748
749   tab->section_index = s->index;
750
751   if (em->first_header.file_class == ELF_64BIT)
752     {
753       tab->symbols = elf_get_section_contents (em, s - em->sections, sizeof (tab->symbols[0]));
754       for (i = 0; i < vec_len (tab->symbols); i++)
755         {
756 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
757           foreach_elf64_symbol_header;
758 #undef _
759         }
760     }
761   else
762     {
763       sym32 = elf_get_section_contents (em, s - em->sections, sizeof (sym32[0]));
764       vec_clone (tab->symbols, sym32);
765       for (i = 0; i < vec_len (tab->symbols); i++)
766         {
767 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
768           foreach_elf32_symbol_header;
769 #undef _
770         }
771     }
772
773   if (s->header.link == 0)
774     return;
775
776   tab->string_table =
777     elf_get_section_contents (em, s->header.link, sizeof (tab->string_table[0]));
778   tab->symbol_by_name
779     = hash_create_string (/* # elts */ vec_len (tab->symbols),
780                           /* sizeof of value */ sizeof (uword));
781
782   vec_foreach (sym64, tab->symbols)
783     {
784       if (sym64->name != 0)
785         hash_set_mem (tab->symbol_by_name,
786                       tab->string_table + sym64->name,
787                       sym64 - tab->symbols);
788     }
789 }
790
791 static void
792 add_relocation_table (elf_main_t * em, elf_section_t * s)
793 {
794   uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
795   elf_relocation_table_t * t;
796   uword i;
797
798   vec_add2 (em->relocation_tables, t, 1);
799   t->section_index = s - em->sections;
800
801   if (em->first_header.file_class == ELF_64BIT)
802     {
803       elf64_relocation_t * r, * rs;
804
805       rs = elf_get_section_contents (em, t->section_index, 
806                                      sizeof (rs[0]) + has_addend * sizeof (rs->addend[0]));
807
808       if (em->need_byte_swap)
809         {
810           r = rs;
811           for (i = 0; i < vec_len (r); i++)
812             {
813               r->address = elf_swap_u64 (em, r->address);
814               r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
815               if (has_addend)
816                 r->addend[0] = elf_swap_u64 (em, r->addend[0]);
817               r = elf_relocation_next (r, s->header.type);
818             }
819         }
820
821       vec_resize (t->relocations, vec_len (rs));
822       clib_memcpy (t->relocations, rs, vec_bytes (t->relocations));
823       vec_free (rs);
824     }
825   else
826     {
827       elf_relocation_with_addend_t * r;
828       elf32_relocation_t * r32, * r32s;
829
830       r32s = elf_get_section_contents (em, t->section_index, 
831                                        sizeof (r32s[0]) + has_addend * sizeof (r32s->addend[0]));
832       vec_resize (t->relocations, vec_len (r32s));
833
834       r32 = r32s;
835       vec_foreach (r, t->relocations)
836         {
837           r->address = elf_swap_u32 (em, r32->address);
838           r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
839           r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0;
840           r32 = elf_relocation_next (r32, s->header.type);
841         }
842
843       vec_free (r32s);
844     }
845 }
846
847 void elf_parse_symbols (elf_main_t * em)
848 {
849   elf_section_t * s;
850
851   /* No need to parse symbols twice. */
852   if (em->parsed_symbols)
853     return;
854   em->parsed_symbols = 1;
855
856   vec_foreach (s, em->sections)
857     {
858       switch (s->header.type)
859         {
860         case ELF_SECTION_SYMBOL_TABLE:
861         case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
862           add_symbol_table (em, s);
863           break;
864
865         case ELF_SECTION_RELOCATION_ADD:
866         case ELF_SECTION_RELOCATION:
867           add_relocation_table (em, s);
868           break;
869
870         default:
871           break;
872         }
873     }
874 }
875
876 void elf_set_dynamic_entries (elf_main_t * em)
877 {
878   uword i;
879
880   /* Start address for sections may have changed. */
881   {
882     elf64_dynamic_entry_t * e;
883
884     vec_foreach (e, em->dynamic_entries)
885       {
886         switch (e->type)
887           {
888           case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
889           case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
890           case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
891           case ELF_DYNAMIC_ENTRY_GNU_HASH:
892           case ELF_DYNAMIC_ENTRY_STRING_TABLE:
893           case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
894           case ELF_DYNAMIC_ENTRY_PLT_GOT:
895           case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
896           case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
897           case ELF_DYNAMIC_ENTRY_VERSION_NEED:
898           case ELF_DYNAMIC_ENTRY_VERSYM:
899             {
900               elf_section_t * es = elf_get_section_by_start_address_no_check (em, e->data);
901               /* If section is not found just leave e->data alone. */
902               if (es)
903                 e->data = es->header.exec_address;
904               break;
905             }
906
907           default:
908             break;
909           }
910       }
911   }
912
913   if (em->first_header.file_class == ELF_64BIT)
914     {
915       elf64_dynamic_entry_t * e, * es;
916
917       es = em->dynamic_entries;
918       if (em->need_byte_swap)
919         {
920           es = vec_dup (es);
921           vec_foreach (e, es)
922             {
923               e->type = elf_swap_u64 (em, e->type);
924               e->data = elf_swap_u64 (em, e->data);
925             }
926         }
927
928       elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
929       if (es != em->dynamic_entries)
930         vec_free (es);
931     }
932   else
933     {
934       elf32_dynamic_entry_t * es;
935
936       vec_clone (es, em->dynamic_entries);
937       if (em->need_byte_swap)
938         {
939           for (i = 0; i < vec_len (es); i++)
940             {
941               es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type);
942               es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data);
943             }
944         }
945
946       elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
947       vec_free (es);
948     }
949 }
950
951 clib_error_t *
952 elf_parse (elf_main_t * em,
953            void * data,
954            uword data_bytes)
955 {
956   elf_first_header_t * h = data;
957   elf64_file_header_t * fh = &em->file_header;
958   clib_error_t * error = 0;
959
960   {
961     char * save = em->file_name;
962     memset (em, 0, sizeof (em[0]));
963     em->file_name = save;
964   }
965
966   em->first_header = h[0];
967   em->need_byte_swap = 
968       CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding == ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
969   elf_swap_first_header (em, &em->first_header);
970
971   if (! (h->magic[0] == 0x7f
972          && h->magic[1] == 'E'
973          && h->magic[2] == 'L'
974          && h->magic[3] == 'F'))
975     return clib_error_return (0, "`%s': bad magic", em->file_name);
976
977   if (h->file_class == ELF_64BIT)
978     {
979       elf64_file_header_t * h64 = (void *) (h + 1);
980 #define _(t,f) fh->f = elf_swap_##t (em, h64->f);
981       foreach_elf64_file_header
982 #undef _
983     }
984   else
985     {
986       elf32_file_header_t * h32 = (void *) (h + 1);
987
988 #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
989       foreach_elf32_file_header
990 #undef _
991     }
992
993   elf_parse_segments (em, data);
994   elf_parse_sections (em, data);
995
996   /* Figure which sections are contained in each segment. */
997   {
998     elf_segment_t * g;
999     elf_section_t * s;
1000     vec_foreach (g, em->segments)
1001       {
1002         u64 g_lo, g_hi;
1003         u64 s_lo, s_hi;
1004
1005         if (g->header.memory_size == 0)
1006           continue;
1007
1008         g_lo = g->header.virtual_address;
1009         g_hi = g_lo + g->header.memory_size;
1010
1011         vec_foreach (s, em->sections)
1012           {
1013             s_lo = s->header.exec_address;
1014             s_hi = s_lo + s->header.file_size;
1015
1016             if (s_lo >= g_lo && s_hi <= g_hi)
1017               {
1018                 g->section_index_bitmap = clib_bitmap_ori (g->section_index_bitmap, s->index);
1019                 s->segment_index_bitmap = clib_bitmap_ori (s->segment_index_bitmap, g->index);
1020               }
1021           }
1022       }
1023   }
1024
1025   return error;
1026 }
1027
1028 #ifdef CLIB_UNIX
1029
1030 static void
1031 add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1032 {
1033   uword i;
1034
1035   /* Can't have more than one dynamic section. */
1036   ASSERT (em->dynamic_section_index == 0);
1037   em->dynamic_section_index = s->index;
1038
1039   if (em->first_header.file_class == ELF_64BIT)
1040     {
1041       elf64_dynamic_entry_t * e;
1042
1043       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1044       if (em->need_byte_swap)
1045         for (i = 0; i < vec_len (e); i++)
1046           {
1047             e[i].type = elf_swap_u64 (em, e[i].type);
1048             e[i].data = elf_swap_u64 (em, e[i].data);
1049           }
1050
1051       em->dynamic_entries = e;
1052     }
1053   else
1054     {
1055       elf32_dynamic_entry_t * e;
1056
1057       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1058       vec_clone (em->dynamic_entries, e);
1059       if (em->need_byte_swap)
1060         for (i = 0; i < vec_len (e); i++)
1061           {
1062             em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type);
1063             em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data);
1064           }
1065
1066       vec_free (e);
1067     }
1068 }
1069
1070 static void byte_swap_verneed (elf_main_t * em,
1071                                elf_dynamic_version_need_union_t * vus)
1072 {
1073   uword * entries_swapped = 0;
1074   uword i, j;
1075
1076   for (i = 0; i < vec_len (vus); i++)
1077     {
1078       elf_dynamic_version_need_union_t * n = vec_elt_at_index (vus, i);
1079       elf_dynamic_version_need_union_t * a;
1080
1081       if (clib_bitmap_get (entries_swapped, i))
1082         continue;
1083
1084       elf_swap_verneed (&n->need);
1085       entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1086
1087       if (n->need.first_aux_offset != 0)
1088         {
1089           ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1090           j = i + (n->need.first_aux_offset / sizeof (n[0]));
1091           while (1)
1092             {
1093               a = vec_elt_at_index (vus, j);
1094               if (! clib_bitmap_get (entries_swapped, j))
1095                 {
1096                   entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1097                   elf_swap_verneed_aux (&a->aux);
1098                 }
1099               if (a->aux.next_offset == 0)
1100                 break;
1101               ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1102               j += (a->aux.next_offset / sizeof (a->aux));
1103             } 
1104         }
1105     }
1106
1107   clib_bitmap_free (entries_swapped);
1108 }
1109
1110 static void
1111 set_dynamic_verneed (elf_main_t * em) __attribute__((unused));
1112 static void
1113 set_dynamic_verneed (elf_main_t * em)
1114 {
1115   elf_dynamic_version_need_union_t * vus = em->verneed;
1116
1117   if (em->need_byte_swap)
1118     {
1119       vus = vec_dup (vus);
1120       byte_swap_verneed (em, vus);
1121     }
1122
1123   elf_set_section_contents (em, em->verneed_section_index, vus, vec_bytes (vus));
1124   if (vus != em->verneed)
1125     vec_free (vus);
1126 }
1127
1128 static void
1129 set_symbol_table (elf_main_t * em, u32 table_index) __attribute__((unused));
1130 static void
1131 set_symbol_table (elf_main_t * em, u32 table_index)
1132 {
1133   elf_symbol_table_t * tab = vec_elt_at_index (em->symbol_tables, table_index);
1134
1135   if (em->first_header.file_class == ELF_64BIT)
1136     {
1137       elf64_symbol_t * s, * syms;
1138       
1139       syms = vec_dup (tab->symbols);
1140       vec_foreach (s, syms)
1141         {
1142 #define _(t,f) s->f = elf_swap_##t (em, s->f);
1143           foreach_elf64_symbol_header;
1144 #undef _
1145         }
1146
1147       elf_set_section_contents (em, tab->section_index,
1148                                 syms, vec_bytes (syms));
1149     }
1150   else
1151     {
1152       elf32_symbol_t * syms;
1153       uword i;
1154       vec_clone (syms, tab->symbols);
1155       for (i = 0; i < vec_len (tab->symbols); i++)
1156         {
1157 #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1158           foreach_elf32_symbol_header;
1159 #undef _
1160         }
1161
1162       elf_set_section_contents (em, tab->section_index,
1163                                 syms, vec_bytes (syms));
1164     }
1165 }
1166
1167 static char *
1168 elf_find_interpreter (elf_main_t * em, void * data)
1169 {
1170   elf_segment_t * g;
1171   elf_section_t * s;
1172   uword * p;
1173
1174   vec_foreach (g, em->segments)
1175     {
1176       if (g->header.type == ELF_SEGMENT_INTERP)
1177         break;
1178     }
1179
1180   if (g >= vec_end (em->segments))
1181     return 0;
1182
1183   p = hash_get (em->section_by_start_address, g->header.virtual_address);
1184   if (! p)
1185     return 0;
1186
1187   s = vec_elt_at_index (em->sections, p[0]);
1188   return (char *) vec_dup (s->contents);
1189 }
1190
1191 static void *
1192 elf_get_section_contents_with_starting_address (elf_main_t * em,
1193                                                 uword start_address,
1194                                                 uword elt_size,
1195                                                 u32 * section_index_result)
1196 {
1197   elf_section_t * s;
1198   clib_error_t * error;
1199
1200   error = elf_get_section_by_start_address (em, start_address, &s);
1201   if (error)
1202     {
1203       clib_error_report (error);
1204       return 0;
1205     }
1206
1207   if (section_index_result)
1208     *section_index_result = s->index;
1209
1210   return elf_get_section_contents (em, s->index, elt_size);
1211 }
1212
1213 static void elf_parse_dynamic (elf_main_t * em)
1214 {
1215   elf_section_t * s;
1216   elf64_dynamic_entry_t * e;
1217
1218   vec_foreach (s, em->sections)
1219     {
1220       switch (s->header.type)
1221         {
1222         case ELF_SECTION_DYNAMIC:
1223           add_dynamic_entries (em, s);
1224           break;
1225
1226         default:
1227           break;
1228         }
1229     }
1230
1231   em->dynamic_string_table_section_index = ~0;
1232   em->dynamic_string_table = 0;
1233
1234   vec_foreach (e, em->dynamic_entries)
1235     {
1236       switch (e->type)
1237         {
1238         case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1239           ASSERT (vec_len (em->dynamic_string_table) == 0);
1240           em->dynamic_string_table
1241             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (u8),
1242                                                               &em->dynamic_string_table_section_index);
1243           break;
1244
1245         case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1246           {
1247             elf_section_t * s;
1248             clib_error_t * error;
1249
1250             error = elf_get_section_by_start_address (em, e->data, &s);
1251             if (error)
1252               {
1253                 clib_error_report (error);
1254                 return;
1255               }
1256
1257             em->dynamic_symbol_table_section_index = s - em->sections;
1258           }
1259           break;
1260
1261         case ELF_DYNAMIC_ENTRY_VERSYM:
1262           em->versym
1263             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->versym[0]),
1264                                                               &em->versym_section_index);
1265           if (em->need_byte_swap)
1266             {
1267               uword i;
1268               for (i = 0; i < vec_len (em->versym); i++)
1269                 em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1270             }
1271           break;
1272
1273         case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1274           em->verneed
1275             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->verneed[0]),
1276                                                               &em->verneed_section_index);
1277           if (em->need_byte_swap)
1278             byte_swap_verneed (em, em->verneed);
1279           break;
1280
1281         default:
1282           break;
1283         }
1284     }
1285 }
1286
1287 #include <sys/types.h>
1288 #include <sys/stat.h>
1289 #include <fcntl.h>
1290
1291 clib_error_t * elf_read_file (elf_main_t * em, char * file_name)
1292 {
1293   int fd;
1294   struct stat fd_stat;
1295   uword mmap_length = 0;
1296   void * data = 0;
1297   clib_error_t * error = 0;
1298
1299   elf_main_init (em);
1300
1301   fd = open (file_name, 0);
1302   if (fd < 0)
1303     {
1304       error = clib_error_return_unix (0, "open `%s'", file_name);
1305       goto done;
1306     }
1307
1308   if (fstat (fd, &fd_stat) < 0)
1309     {
1310       error = clib_error_return_unix (0, "fstat `%s'", file_name);
1311       goto done;
1312     }
1313   mmap_length = fd_stat.st_size;
1314
1315   data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0);
1316   if (~pointer_to_uword (data) == 0)
1317     {
1318       error = clib_error_return_unix (0, "mmap `%s'", file_name);
1319       goto done;
1320     }
1321
1322   em->file_name = file_name;
1323
1324   error = elf_parse (em, data, mmap_length);
1325   if (error)
1326     goto done;
1327
1328   elf_parse_symbols (em);
1329   elf_parse_dynamic (em);
1330
1331   em->interpreter = elf_find_interpreter (em, data);
1332
1333   munmap (data, mmap_length);
1334   close (fd);
1335
1336   return /* no error */ 0;
1337
1338  done:
1339   elf_main_free (em);
1340   if (fd >= 0)
1341     close (fd);
1342   if (data)
1343     munmap (data, mmap_length);
1344   return error;
1345 }
1346
1347 typedef struct {
1348   u8 * new_table;
1349
1350   u8 * old_table;
1351
1352   uword * hash;
1353 } string_table_builder_t;
1354
1355 static u32 string_table_add_name (string_table_builder_t * b, u8 * n)
1356 {
1357   uword * p, i, j, l;
1358
1359   p = hash_get_mem (b->hash, n);
1360   if (p) return p[0];
1361
1362   l = strlen ((char *) n);
1363   i = vec_len (b->new_table);
1364   vec_add (b->new_table, n, l + 1);
1365
1366   for (j = 0; j <= l; j++)
1367     {
1368       if (j > 0)
1369         {
1370           p = hash_get_mem (b->hash, n + j);
1371
1372           /* Sub-string already in table? */
1373           if (p)
1374             continue;
1375         }
1376
1377       hash_set_mem (b->hash, n + j, i + j);
1378     }
1379
1380   return i;
1381 }
1382
1383 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1384     __attribute__((unused));
1385 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1386 {
1387   u8 * n = b->old_table + index;
1388   return string_table_add_name (b, n);
1389 }
1390
1391 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1392     __attribute__((unused));
1393 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1394 {
1395   memset (b, 0, sizeof (b[0]));
1396   b->old_table = old_table;
1397   b->hash = hash_create_string (0, sizeof (uword));
1398 }
1399
1400 static u8 * string_table_done (string_table_builder_t * b)
1401     __attribute__((unused));
1402 static u8 * string_table_done (string_table_builder_t * b)
1403 {
1404   hash_free (b->hash);
1405   return b->new_table;
1406 }
1407
1408 static void layout_sections (elf_main_t * em)
1409 {
1410   elf_section_t * s;
1411   u32 n_sections_with_changed_exec_address = 0;
1412   u32 * deferred_symbol_and_string_sections = 0;
1413   u32 n_deleted_sections = 0;
1414   /* note: rebuild is always zero. Intent lost in the sands of time */
1415 #if 0 
1416   int rebuild = 0;
1417
1418   /* Re-build section string table (sections may have been deleted). */
1419   if (rebuild)
1420     {
1421       u8 * st = 0;
1422
1423       vec_foreach (s, em->sections)
1424         {
1425           u8 * name;
1426           if (s->header.type == ~0)
1427             continue;
1428           name = elf_section_name (em, s);
1429           s->header.name = vec_len (st);
1430           vec_add (st, name, strlen ((char *) name) + 1);
1431         }
1432
1433       s = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1434
1435       vec_free (s->contents);
1436       s->contents = st;
1437     }
1438
1439   /* Re-build dynamic string table. */
1440   if (rebuild && em->dynamic_string_table_section_index != ~0)
1441     {
1442       string_table_builder_t b;
1443     
1444       string_table_init (&b, em->dynamic_string_table);
1445
1446       /* Add all dynamic symbols. */
1447       {
1448         elf_symbol_table_t * symtab;
1449         elf64_symbol_t * sym;
1450
1451         symtab = vec_elt_at_index (em->symbol_tables, em->dynamic_symbol_table_index);
1452         vec_foreach (sym, symtab->symbols)
1453           {
1454             u8 * name = elf_symbol_name (symtab, sym);
1455             sym->name = string_table_add_name (&b, name);
1456           }
1457
1458         set_symbol_table (em, em->dynamic_symbol_table_index);
1459       }
1460
1461       /* Add all dynamic entries. */
1462       {
1463         elf64_dynamic_entry_t * e;
1464
1465         vec_foreach (e, em->dynamic_entries)
1466           {
1467             switch (e->type)
1468               {
1469               case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1470               case ELF_DYNAMIC_ENTRY_RPATH:
1471               case ELF_DYNAMIC_ENTRY_RUN_PATH:
1472                 e->data = string_table_add_name_index (&b, e->data);
1473                 break;
1474               }
1475           }
1476       }
1477
1478       /* Add all version needs. */
1479       if (vec_len (em->verneed) > 0)
1480         {
1481           elf_dynamic_version_need_union_t * n, * a;
1482
1483           n = em->verneed;
1484           while (1)
1485             {
1486               n->need.file_name_offset = string_table_add_name_index (&b, n->need.file_name_offset);
1487
1488               if (n->need.first_aux_offset != 0)
1489                 {
1490                   a = n + n->need.first_aux_offset / sizeof (n[0]);
1491                   while (1)
1492                     {
1493                       a->aux.name = string_table_add_name_index (&b, a->aux.name);
1494                       if (a->aux.next_offset == 0)
1495                         break;
1496                       a += a->aux.next_offset / sizeof (a[0]);
1497                     }
1498                 }
1499
1500               if (n->need.next_offset == 0)
1501                 break;
1502
1503               n += n->need.next_offset / sizeof (n[0]);
1504             }
1505
1506           set_dynamic_verneed (em);
1507         }
1508
1509       s = vec_elt_at_index (em->sections, em->dynamic_string_table_section_index);
1510
1511       vec_free (s->contents);
1512       s->contents = string_table_done (&b);
1513     }
1514 #endif /* dead code */
1515
1516   /* Figure file offsets and exec addresses for sections. */
1517   {
1518     u64 exec_address = 0, file_offset = 0;
1519     u64 file_size, align_size;
1520
1521     vec_foreach (s, em->sections)
1522       {
1523         /* Ignore deleted and unused sections. */
1524         switch (s->header.type)
1525           {
1526           case ~0:
1527             n_deleted_sections++;
1528           case ELF_SECTION_UNUSED:
1529             continue;
1530
1531           case ELF_SECTION_STRING_TABLE:
1532           case ELF_SECTION_SYMBOL_TABLE:
1533             if (! (s->index == em->dynamic_string_table_section_index
1534                    || s->index == em->file_header.section_header_string_table_index))
1535               {
1536                 vec_add1 (deferred_symbol_and_string_sections, s->index);
1537                 continue;
1538               }
1539             break;
1540
1541           default:
1542             break;
1543           }
1544
1545         exec_address = round_pow2_u64 (exec_address, s->header.align);
1546
1547         /* Put sections we added at end of file. */
1548         if (s->header.file_offset == ~0)
1549           s->header.file_offset = file_offset;
1550
1551         /* Follow gaps in original file. */
1552         if (s->header.exec_address > exec_address)
1553           {
1554             exec_address = s->header.exec_address;
1555             file_offset = s->header.file_offset;
1556           }
1557
1558         if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1559           {
1560             s->exec_address_change = exec_address - s->header.exec_address;
1561             n_sections_with_changed_exec_address += s->exec_address_change != 0;
1562             s->header.exec_address = exec_address;
1563           }
1564
1565         if (s->header.type == ELF_SECTION_NO_BITS)
1566           file_size = s->header.file_size;
1567         else
1568           file_size = vec_len (s->contents);
1569
1570         {
1571           u64 align;
1572
1573           if (s + 1 >= vec_end (em->sections))
1574             align = 16;
1575           else if (s[1].header.type == ELF_SECTION_NO_BITS)
1576             align = 8;
1577           else
1578             align = s[1].header.align;
1579
1580           if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1581             {
1582               u64 v = round_pow2_u64 (exec_address + file_size, align);
1583               align_size = v - exec_address;
1584             }
1585           else
1586             {
1587               u64 v = round_pow2_u64 (file_offset + file_size, align);
1588               align_size = v - file_offset;
1589             }
1590         }
1591
1592         s->header.file_offset = file_offset;
1593         s->header.file_size = file_size;
1594         s->align_size = align_size;
1595
1596         if (s->header.type != ELF_SECTION_NO_BITS)
1597           file_offset += align_size;
1598         exec_address += align_size;
1599       }
1600
1601     /* Section headers go after last section but before symbol/string
1602        tables. */
1603     {
1604       elf64_file_header_t * fh = &em->file_header;
1605
1606       fh->section_header_file_offset = file_offset;
1607       fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1608       file_offset += (u64) fh->section_header_count * fh->section_header_size;
1609     }
1610
1611     {
1612       int i;
1613       for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1614         {
1615           s = vec_elt_at_index (em->sections, deferred_symbol_and_string_sections[i]);
1616
1617           s->header.file_offset = file_offset;
1618           s->header.file_size = vec_len (s->contents);
1619
1620           align_size = round_pow2 (vec_len (s->contents), 16);
1621           s->align_size = align_size;
1622           file_offset += align_size;
1623         }
1624       vec_free (deferred_symbol_and_string_sections);
1625     }
1626   }
1627
1628   /* Update dynamic entries now that sections have been assigned
1629      possibly new addresses. */
1630 #if 0
1631   if (rebuild)
1632     elf_set_dynamic_entries (em);
1633 #endif
1634
1635   /* Update segments for changed section addresses. */
1636   {
1637     elf_segment_t * g;
1638     uword si;
1639
1640     vec_foreach (g, em->segments)
1641       {
1642         u64 s_lo, s_hi, f_lo = 0;
1643         u32 n_sections = 0;
1644
1645         if (g->header.memory_size == 0)
1646           continue;
1647
1648         s_lo = s_hi = 0;
1649         clib_bitmap_foreach (si, g->section_index_bitmap, ({
1650           u64 lo, hi;
1651
1652           s = vec_elt_at_index (em->sections, si);
1653           lo = s->header.exec_address;
1654           hi = lo + s->align_size;
1655           if (n_sections == 0)
1656             {
1657               s_lo = lo;
1658               s_hi = hi;
1659               f_lo = s->header.file_offset;
1660               n_sections++;
1661             }
1662           else
1663             {
1664               if (lo < s_lo)
1665                 {
1666                   s_lo = lo;
1667                   f_lo = s->header.file_offset;
1668                 }
1669               if (hi > s_hi)
1670                 s_hi = hi;
1671             }
1672         }));
1673
1674         if (n_sections == 0)
1675           continue;
1676
1677         /* File offset zero includes ELF headers/segment headers.
1678            Don't change that. */
1679         if (g->header.file_offset == 0
1680             && g->header.type == ELF_SEGMENT_LOAD)
1681           {
1682             s_lo = g->header.virtual_address;
1683             f_lo = g->header.file_offset;
1684           }
1685
1686         g->header.virtual_address = s_lo;
1687         g->header.physical_address = s_lo;
1688         g->header.file_offset = f_lo;
1689         g->header.memory_size = s_hi - s_lo;
1690       }
1691   }
1692 }
1693
1694 clib_error_t * elf_write_file (elf_main_t * em, char * file_name)
1695 {
1696   int fd;
1697   FILE * f;
1698   clib_error_t * error = 0;
1699
1700   fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1701   if (fd < 0)
1702     return clib_error_return_unix (0, "open `%s'", file_name);
1703
1704   f = fdopen (fd, "w");
1705
1706   /* Section contents may have changed.  So, we need to update
1707      stuff to reflect this. */
1708   layout_sections (em);
1709
1710   /* Write first header. */
1711   {
1712     elf_first_header_t h = em->first_header;
1713
1714     elf_swap_first_header (em, &h);
1715     if (fwrite (&h, sizeof (h), 1, f) != 1)
1716       {
1717         error = clib_error_return_unix (0, "write first header");
1718         goto error;
1719       }
1720   }
1721
1722   /* Write file header. */
1723   {
1724     elf64_file_header_t h = em->file_header;
1725
1726     /* Segment headers are after first header. */
1727     h.segment_header_file_offset = sizeof (elf_first_header_t);
1728     if (em->first_header.file_class == ELF_64BIT)
1729       h.segment_header_file_offset += sizeof (elf64_file_header_t);
1730     else
1731       h.segment_header_file_offset += sizeof (elf32_file_header_t);
1732
1733     if (em->first_header.file_class == ELF_64BIT)
1734       {
1735 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1736         foreach_elf64_file_header;
1737 #undef _
1738
1739       if (fwrite (&h, sizeof (h), 1, f) != 1)
1740         {
1741           error = clib_error_return_unix (0, "write file header");
1742           goto error;
1743         }
1744     }
1745   else
1746     {
1747       elf32_file_header_t h32;
1748
1749 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1750       foreach_elf32_file_header;
1751 #undef _
1752
1753       if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1754         {
1755           error = clib_error_return_unix (0, "write file header");
1756           goto error;
1757         }
1758     }
1759   }
1760
1761   /* Write segment headers. */
1762   {
1763     elf_segment_t * s;
1764
1765     vec_foreach (s, em->segments)
1766       {
1767         elf64_segment_header_t h;
1768
1769         if (s->header.type == ~0)
1770           continue;
1771
1772         h = s->header;
1773
1774         if (em->first_header.file_class == ELF_64BIT)
1775           {
1776 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1777             foreach_elf64_segment_header;
1778 #undef _
1779             
1780             if (fwrite (&h, sizeof (h), 1, f) != 1)
1781               {
1782                 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1783                 goto error;
1784               }
1785           }
1786         else
1787           {
1788             elf32_segment_header_t h32;
1789
1790 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1791             foreach_elf32_segment_header;
1792 #undef _
1793
1794             if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1795               {
1796                 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1797                 goto error;
1798               }
1799           }
1800       }
1801   }
1802
1803   /* Write contents for all sections. */
1804   {
1805     elf_section_t * s;
1806
1807     vec_foreach (s, em->sections)
1808       {
1809         if (s->header.file_size == 0)
1810           continue;
1811
1812         if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1813           {
1814             fclose(f);
1815             return clib_error_return_unix (0, "fseek 0x%Lx", 
1816                                            s->header.file_offset);
1817           }
1818
1819         if (s->header.type == ELF_SECTION_NO_BITS)
1820           /* don't write for .bss sections */;
1821         else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1822           {
1823             error = clib_error_return_unix (0, "write %s section contents", elf_section_name (em, s));
1824             goto error;
1825           }
1826       }
1827
1828     /* Finally write section headers. */
1829     if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1830       {
1831         fclose(f);
1832         return clib_error_return_unix 
1833           (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1834       }
1835         
1836     vec_foreach (s, em->sections)
1837       {
1838         elf64_section_header_t h;
1839
1840         if (s->header.type == ~0)
1841           continue;
1842
1843         h = s->header;
1844
1845         if (em->first_header.file_class == ELF_64BIT)
1846           {
1847 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1848             foreach_elf64_section_header;
1849 #undef _
1850             
1851             if (fwrite (&h, sizeof (h), 1, f) != 1)
1852               {
1853                 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1854                 goto error;
1855               }
1856           }
1857         else
1858           {
1859             elf32_section_header_t h32;
1860
1861 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1862             foreach_elf32_section_header;
1863 #undef _
1864
1865             if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1866               {
1867                 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1868                 goto error;
1869               }
1870           }
1871       }
1872   }
1873
1874  error:
1875   fclose (f);
1876   return error;
1877 }
1878
1879 clib_error_t * elf_delete_named_section (elf_main_t * em, char * section_name)
1880 {
1881   elf_section_t * s;
1882   clib_error_t * error;
1883
1884   error = elf_get_section_by_name (em, section_name, &s);
1885   if (error)
1886     return error;
1887   
1888   s->header.type = ~0;
1889
1890   return 0;
1891 }
1892
1893 void
1894 elf_create_section_with_contents (elf_main_t * em,
1895                                   char * section_name,
1896                                   elf64_section_header_t * header,
1897                                   void * contents,
1898                                   uword n_content_bytes)
1899 {
1900   elf_section_t * s, * sts;
1901   u8 * st, * c;
1902   uword * p, is_new_section;
1903
1904   /* See if section already exists with given name.
1905      If so, just replace contents. */
1906   is_new_section = 0;
1907   if ((p = hash_get_mem (em->section_by_name, section_name)))
1908     {
1909       s = vec_elt_at_index (em->sections, p[0]);
1910       _vec_len (s->contents) = 0;
1911       c = s->contents;
1912     }
1913   else
1914     {
1915       vec_add2 (em->sections, s, 1);
1916       is_new_section = 1;
1917       c = 0;
1918     }
1919
1920   sts = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1921   st = sts->contents;
1922
1923   s->header = header[0];
1924
1925   s->header.file_offset = ~0;
1926   s->header.file_size = n_content_bytes;
1927   s->index = s - em->sections;
1928
1929   /* Add name to string table. */
1930   s->header.name = vec_len (st);
1931   vec_add (st, section_name, strlen (section_name));
1932   vec_add1 (st, 0);
1933   sts->contents = st;
1934
1935   vec_resize (c, n_content_bytes);
1936   clib_memcpy (c, contents, n_content_bytes);
1937   s->contents = c;
1938
1939   em->file_header.section_header_count += is_new_section && s->header.type != ~0;
1940 }
1941
1942 uword elf_delete_segment_with_type (elf_main_t * em, elf_segment_type_t segment_type)
1943 {
1944   uword n_deleted = 0;
1945   elf_segment_t * s;
1946
1947   vec_foreach (s, em->segments)
1948     if (s->header.type == segment_type)
1949       {
1950         s->header.type = ~0;
1951         n_deleted += 1;
1952       }
1953
1954   ASSERT (em->file_header.segment_header_count >= n_deleted);
1955   em->file_header.segment_header_count -= n_deleted;
1956
1957   return n_deleted;
1958 }
1959
1960 #endif /* CLIB_UNIX */