Initial commit of vpp code.
[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 + fh->section_header_count * fh->section_header_size);
563     s = format (s, "%U\n", format_elf_section, em, 0);
564     vec_foreach (h, copy)
565       s = format (s, "%U\n", format_elf_section, em, h);
566
567     vec_free (copy);
568   }
569
570   {
571     elf_segment_t * h, * copy;
572
573     copy = 0;
574     vec_foreach (h, em->segments)
575       if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0)
576         vec_add1 (copy, h[0]);
577
578     /* Sort segments by address. */
579     vec_sort_with_function (copy, elf_segment_va_compare);
580
581     s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n",
582                 fh->segment_header_count,
583                 fh->segment_header_file_offset,
584                 fh->segment_header_file_offset + fh->segment_header_count * fh->segment_header_size);
585                 
586     s = format (s, "%U\n", format_elf_segment, 0);
587     vec_foreach (h, copy)
588       s = format (s, "%U\n", format_elf_segment, h);
589
590     vec_free (copy);
591   }
592
593   if ((verbose & FORMAT_ELF_MAIN_SYMBOLS)
594       && vec_len (em->symbol_tables) > 0)
595     {
596       elf_symbol_table_t * t;
597       elf64_symbol_t * sym;
598       elf_section_t * es;
599
600       vec_foreach (t, em->symbol_tables)
601         {
602           es = vec_elt_at_index (em->sections, t->section_index);
603           s = format (s, "\nSymbols for section %s:\n", elf_section_name (em, es));
604
605           s = format (s, "%U\n", format_elf_symbol, em, 0, 0);
606           vec_foreach (sym, t->symbols)
607             s = format (s, "%U\n", format_elf_symbol, em, t, sym);
608         }
609     }
610
611   if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS)
612       && vec_len (em->relocation_tables) > 0)
613     {
614       elf_relocation_table_t * t;
615       elf_relocation_with_addend_t * r;
616       elf_section_t * es;
617
618       vec_foreach (t, em->relocation_tables)
619         {
620           es = vec_elt_at_index (em->sections, t->section_index);
621           r = t->relocations;
622           s = format (s, "\nRelocations for section %s:\n",
623                       elf_section_name (em, es));
624
625           s = format (s, "%U\n", format_elf_relocation, em, 0);
626           vec_foreach (r, t->relocations)
627             {
628               s = format (s, "%U\n",
629                           format_elf_relocation, em, r);
630             }
631         }
632     }
633
634   if ((verbose & FORMAT_ELF_MAIN_DYNAMIC)
635       && vec_len (em->dynamic_entries) > 0)
636     {
637       elf64_dynamic_entry_t * es, * e;
638       s = format (s, "\nDynamic linker information:\n");
639       es = vec_dup (em->dynamic_entries);
640       s = format (s, "%U\n", format_elf_dynamic_entry, em, 0);
641       vec_foreach (e, es)
642         s = format (s, "%U\n", format_elf_dynamic_entry, em, e);
643     }
644
645   return s;
646 }
647
648 static void
649 elf_parse_segments (elf_main_t * em, void * data)
650 {
651   void * d = data + em->file_header.segment_header_file_offset;
652   uword n = em->file_header.segment_header_count;
653   uword i;
654
655   vec_resize (em->segments, n);
656
657   for (i = 0; i < n; i++)
658     {
659       em->segments[i].index = i;
660
661       if (em->first_header.file_class == ELF_64BIT)
662         {
663           elf64_segment_header_t * h = d;
664 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
665           foreach_elf64_segment_header
666 #undef _
667           d = (h + 1);
668         }
669       else
670         {
671           elf32_segment_header_t * h = d;
672 #define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f);
673           foreach_elf32_segment_header
674 #undef _
675           d = (h + 1);
676         }
677     }
678 }
679
680 static void
681 elf_parse_sections (elf_main_t * em, void * data)
682 {
683   elf64_file_header_t * fh = &em->file_header;
684   elf_section_t * s;
685   void * d = data + fh->section_header_file_offset;
686   uword n = fh->section_header_count;
687   uword i;
688
689   vec_resize (em->sections, n);
690
691   for (i = 0; i < n; i++)
692     {
693       s = em->sections + i;
694
695       s->index = i;
696
697       if (em->first_header.file_class == ELF_64BIT)
698         {
699           elf64_section_header_t * h = d;
700 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
701           foreach_elf64_section_header
702 #undef _
703           d = (h + 1);
704         }
705       else
706         {
707           elf32_section_header_t * h = d;
708 #define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f);
709           foreach_elf32_section_header
710 #undef _
711           d = (h + 1);
712         }
713
714       if (s->header.type != ELF_SECTION_NO_BITS)
715         vec_add (s->contents, data + s->header.file_offset, s->header.file_size);
716     }
717
718   s = vec_elt_at_index (em->sections, fh->section_header_string_table_index);
719
720   em->section_by_name
721     = hash_create_string (/* # elts */ vec_len (em->sections),
722                           /* sizeof of value */ sizeof (uword));
723
724   vec_foreach (s, em->sections)
725     {
726       hash_set_mem (em->section_by_name,
727                     elf_section_name (em, s),
728                     s - em->sections);
729       hash_set (em->section_by_start_address,
730                 s->header.exec_address,
731                 s - em->sections);
732     }
733 }
734
735 static void
736 add_symbol_table (elf_main_t * em, elf_section_t * s)
737 {
738   elf_symbol_table_t * tab;
739   elf32_symbol_t * sym32;
740   elf64_symbol_t * sym64;
741   uword i;
742
743   if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE)
744     em->dynamic_symbol_table_index = vec_len (em->symbol_tables);
745
746   vec_add2 (em->symbol_tables, tab, 1);
747
748   tab->section_index = s->index;
749
750   if (em->first_header.file_class == ELF_64BIT)
751     {
752       tab->symbols = elf_get_section_contents (em, s - em->sections, sizeof (tab->symbols[0]));
753       for (i = 0; i < vec_len (tab->symbols); i++)
754         {
755 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f);
756           foreach_elf64_symbol_header;
757 #undef _
758         }
759     }
760   else
761     {
762       sym32 = elf_get_section_contents (em, s - em->sections, sizeof (sym32[0]));
763       vec_clone (tab->symbols, sym32);
764       for (i = 0; i < vec_len (tab->symbols); i++)
765         {
766 #define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f);
767           foreach_elf32_symbol_header;
768 #undef _
769         }
770     }
771
772   if (s->header.link == 0)
773     return;
774
775   tab->string_table =
776     elf_get_section_contents (em, s->header.link, sizeof (tab->string_table[0]));
777   tab->symbol_by_name
778     = hash_create_string (/* # elts */ vec_len (tab->symbols),
779                           /* sizeof of value */ sizeof (uword));
780
781   vec_foreach (sym64, tab->symbols)
782     {
783       if (sym64->name != 0)
784         hash_set_mem (tab->symbol_by_name,
785                       tab->string_table + sym64->name,
786                       sym64 - tab->symbols);
787     }
788 }
789
790 static void
791 add_relocation_table (elf_main_t * em, elf_section_t * s)
792 {
793   uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD;
794   elf_relocation_table_t * t;
795   uword i;
796
797   vec_add2 (em->relocation_tables, t, 1);
798   t->section_index = s - em->sections;
799
800   if (em->first_header.file_class == ELF_64BIT)
801     {
802       elf64_relocation_t * r, * rs;
803
804       rs = elf_get_section_contents (em, t->section_index, 
805                                      sizeof (rs[0]) + has_addend * sizeof (rs->addend[0]));
806
807       if (em->need_byte_swap)
808         {
809           r = rs;
810           for (i = 0; i < vec_len (r); i++)
811             {
812               r->address = elf_swap_u64 (em, r->address);
813               r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
814               if (has_addend)
815                 r->addend[0] = elf_swap_u64 (em, r->addend[0]);
816               r = elf_relocation_next (r, s->header.type);
817             }
818         }
819
820       vec_resize (t->relocations, vec_len (rs));
821       memcpy (t->relocations, rs, vec_bytes (t->relocations));
822       vec_free (rs);
823     }
824   else
825     {
826       elf_relocation_with_addend_t * r;
827       elf32_relocation_t * r32, * r32s;
828
829       r32s = elf_get_section_contents (em, t->section_index, 
830                                        sizeof (r32s[0]) + has_addend * sizeof (r32s->addend[0]));
831       vec_resize (t->relocations, vec_len (r32s));
832
833       r32 = r32s;
834       vec_foreach (r, t->relocations)
835         {
836           r->address = elf_swap_u32 (em, r32->address);
837           r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type);
838           r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0;
839           r32 = elf_relocation_next (r32, s->header.type);
840         }
841
842       vec_free (r32s);
843     }
844 }
845
846 void elf_parse_symbols (elf_main_t * em)
847 {
848   elf_section_t * s;
849
850   /* No need to parse symbols twice. */
851   if (em->parsed_symbols)
852     return;
853   em->parsed_symbols = 1;
854
855   vec_foreach (s, em->sections)
856     {
857       switch (s->header.type)
858         {
859         case ELF_SECTION_SYMBOL_TABLE:
860         case ELF_SECTION_DYNAMIC_SYMBOL_TABLE:
861           add_symbol_table (em, s);
862           break;
863
864         case ELF_SECTION_RELOCATION_ADD:
865         case ELF_SECTION_RELOCATION:
866           add_relocation_table (em, s);
867           break;
868
869         default:
870           break;
871         }
872     }
873 }
874
875 void elf_set_dynamic_entries (elf_main_t * em)
876 {
877   uword i;
878
879   /* Start address for sections may have changed. */
880   {
881     elf64_dynamic_entry_t * e;
882
883     vec_foreach (e, em->dynamic_entries)
884       {
885         switch (e->type)
886           {
887           case ELF_DYNAMIC_ENTRY_INIT_FUNCTION:
888           case ELF_DYNAMIC_ENTRY_FINI_FUNCTION:
889           case ELF_DYNAMIC_ENTRY_SYMBOL_HASH:
890           case ELF_DYNAMIC_ENTRY_GNU_HASH:
891           case ELF_DYNAMIC_ENTRY_STRING_TABLE:
892           case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
893           case ELF_DYNAMIC_ENTRY_PLT_GOT:
894           case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS:
895           case ELF_DYNAMIC_ENTRY_RELA_ADDRESS:
896           case ELF_DYNAMIC_ENTRY_VERSION_NEED:
897           case ELF_DYNAMIC_ENTRY_VERSYM:
898             {
899               elf_section_t * es = elf_get_section_by_start_address_no_check (em, e->data);
900               /* If section is not found just leave e->data alone. */
901               if (es)
902                 e->data = es->header.exec_address;
903               break;
904             }
905
906           default:
907             break;
908           }
909       }
910   }
911
912   if (em->first_header.file_class == ELF_64BIT)
913     {
914       elf64_dynamic_entry_t * e, * es;
915
916       es = em->dynamic_entries;
917       if (em->need_byte_swap)
918         {
919           es = vec_dup (es);
920           vec_foreach (e, es)
921             {
922               e->type = elf_swap_u64 (em, e->type);
923               e->data = elf_swap_u64 (em, e->data);
924             }
925         }
926
927       elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
928       if (es != em->dynamic_entries)
929         vec_free (es);
930     }
931   else
932     {
933       elf32_dynamic_entry_t * es;
934
935       vec_clone (es, em->dynamic_entries);
936       if (em->need_byte_swap)
937         {
938           for (i = 0; i < vec_len (es); i++)
939             {
940               es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type);
941               es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data);
942             }
943         }
944
945       elf_set_section_contents (em, em->dynamic_section_index, es, vec_bytes (es));
946       vec_free (es);
947     }
948 }
949
950 clib_error_t *
951 elf_parse (elf_main_t * em,
952            void * data,
953            uword data_bytes)
954 {
955   elf_first_header_t * h = data;
956   elf64_file_header_t * fh = &em->file_header;
957   clib_error_t * error = 0;
958
959   {
960     char * save = em->file_name;
961     memset (em, 0, sizeof (em[0]));
962     em->file_name = save;
963   }
964
965   em->first_header = h[0];
966   em->need_byte_swap = 
967       CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding == ELF_TWOS_COMPLEMENT_BIG_ENDIAN);
968   elf_swap_first_header (em, &em->first_header);
969
970   if (! (h->magic[0] == 0x7f
971          && h->magic[1] == 'E'
972          && h->magic[2] == 'L'
973          && h->magic[3] == 'F'))
974     return clib_error_return (0, "`%s': bad magic", em->file_name);
975
976   if (h->file_class == ELF_64BIT)
977     {
978       elf64_file_header_t * h64 = (void *) (h + 1);
979 #define _(t,f) fh->f = elf_swap_##t (em, h64->f);
980       foreach_elf64_file_header
981 #undef _
982     }
983   else
984     {
985       elf32_file_header_t * h32 = (void *) (h + 1);
986
987 #define _(t,f) fh->f = elf_swap_##t (em, h32->f);
988       foreach_elf32_file_header
989 #undef _
990     }
991
992   elf_parse_segments (em, data);
993   elf_parse_sections (em, data);
994
995   /* Figure which sections are contained in each segment. */
996   {
997     elf_segment_t * g;
998     elf_section_t * s;
999     vec_foreach (g, em->segments)
1000       {
1001         u64 g_lo, g_hi;
1002         u64 s_lo, s_hi;
1003
1004         if (g->header.memory_size == 0)
1005           continue;
1006
1007         g_lo = g->header.virtual_address;
1008         g_hi = g_lo + g->header.memory_size;
1009
1010         vec_foreach (s, em->sections)
1011           {
1012             s_lo = s->header.exec_address;
1013             s_hi = s_lo + s->header.file_size;
1014
1015             if (s_lo >= g_lo && s_hi <= g_hi)
1016               {
1017                 g->section_index_bitmap = clib_bitmap_ori (g->section_index_bitmap, s->index);
1018                 s->segment_index_bitmap = clib_bitmap_ori (s->segment_index_bitmap, g->index);
1019               }
1020           }
1021       }
1022   }
1023
1024   return error;
1025 }
1026
1027 #ifdef CLIB_UNIX
1028
1029 static void
1030 add_dynamic_entries (elf_main_t * em, elf_section_t * s)
1031 {
1032   uword i;
1033
1034   /* Can't have more than one dynamic section. */
1035   ASSERT (em->dynamic_section_index == 0);
1036   em->dynamic_section_index = s->index;
1037
1038   if (em->first_header.file_class == ELF_64BIT)
1039     {
1040       elf64_dynamic_entry_t * e;
1041
1042       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1043       if (em->need_byte_swap)
1044         for (i = 0; i < vec_len (e); i++)
1045           {
1046             e[i].type = elf_swap_u64 (em, e[i].type);
1047             e[i].data = elf_swap_u64 (em, e[i].data);
1048           }
1049
1050       em->dynamic_entries = e;
1051     }
1052   else
1053     {
1054       elf32_dynamic_entry_t * e;
1055
1056       e = elf_get_section_contents (em, s - em->sections, sizeof (e[0]));
1057       vec_clone (em->dynamic_entries, e);
1058       if (em->need_byte_swap)
1059         for (i = 0; i < vec_len (e); i++)
1060           {
1061             em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type);
1062             em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data);
1063           }
1064
1065       vec_free (e);
1066     }
1067 }
1068
1069 static void byte_swap_verneed (elf_main_t * em,
1070                                elf_dynamic_version_need_union_t * vus)
1071 {
1072   uword * entries_swapped = 0;
1073   uword i, j;
1074
1075   for (i = 0; i < vec_len (vus); i++)
1076     {
1077       elf_dynamic_version_need_union_t * n = vec_elt_at_index (vus, i);
1078       elf_dynamic_version_need_union_t * a;
1079
1080       if (clib_bitmap_get (entries_swapped, i))
1081         continue;
1082
1083       elf_swap_verneed (&n->need);
1084       entries_swapped = clib_bitmap_set (entries_swapped, i, 1);
1085
1086       if (n->need.first_aux_offset != 0)
1087         {
1088           ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0);
1089           j = i + (n->need.first_aux_offset / sizeof (n[0]));
1090           while (1)
1091             {
1092               a = vec_elt_at_index (vus, j);
1093               if (! clib_bitmap_get (entries_swapped, j))
1094                 {
1095                   entries_swapped = clib_bitmap_set (entries_swapped, j, 1);
1096                   elf_swap_verneed_aux (&a->aux);
1097                 }
1098               if (a->aux.next_offset == 0)
1099                 break;
1100               ASSERT (a->aux.next_offset % sizeof (a->aux) == 0);
1101               j += (a->aux.next_offset / sizeof (a->aux));
1102             } 
1103         }
1104     }
1105
1106   clib_bitmap_free (entries_swapped);
1107 }
1108
1109 static void
1110 set_dynamic_verneed (elf_main_t * em)
1111 {
1112   elf_dynamic_version_need_union_t * vus = em->verneed;
1113
1114   if (em->need_byte_swap)
1115     {
1116       vus = vec_dup (vus);
1117       byte_swap_verneed (em, vus);
1118     }
1119
1120   elf_set_section_contents (em, em->verneed_section_index, vus, vec_bytes (vus));
1121   if (vus != em->verneed)
1122     vec_free (vus);
1123 }
1124
1125 static void
1126 set_symbol_table (elf_main_t * em, u32 table_index)
1127 {
1128   elf_symbol_table_t * tab = vec_elt_at_index (em->symbol_tables, table_index);
1129
1130   if (em->first_header.file_class == ELF_64BIT)
1131     {
1132       elf64_symbol_t * s, * syms;
1133       
1134       syms = vec_dup (tab->symbols);
1135       vec_foreach (s, syms)
1136         {
1137 #define _(t,f) s->f = elf_swap_##t (em, s->f);
1138           foreach_elf64_symbol_header;
1139 #undef _
1140         }
1141
1142       elf_set_section_contents (em, tab->section_index,
1143                                 syms, vec_bytes (syms));
1144     }
1145   else
1146     {
1147       elf32_symbol_t * syms;
1148       uword i;
1149       vec_clone (syms, tab->symbols);
1150       for (i = 0; i < vec_len (tab->symbols); i++)
1151         {
1152 #define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f);
1153           foreach_elf32_symbol_header;
1154 #undef _
1155         }
1156
1157       elf_set_section_contents (em, tab->section_index,
1158                                 syms, vec_bytes (syms));
1159     }
1160 }
1161
1162 static char *
1163 elf_find_interpreter (elf_main_t * em, void * data)
1164 {
1165   elf_segment_t * g;
1166   elf_section_t * s;
1167   uword * p;
1168
1169   vec_foreach (g, em->segments)
1170     {
1171       if (g->header.type == ELF_SEGMENT_INTERP)
1172         break;
1173     }
1174
1175   if (g >= vec_end (em->segments))
1176     return 0;
1177
1178   p = hash_get (em->section_by_start_address, g->header.virtual_address);
1179   if (! p)
1180     return 0;
1181
1182   s = vec_elt_at_index (em->sections, p[0]);
1183   return (char *) vec_dup (s->contents);
1184 }
1185
1186 static void *
1187 elf_get_section_contents_with_starting_address (elf_main_t * em,
1188                                                 uword start_address,
1189                                                 uword elt_size,
1190                                                 u32 * section_index_result)
1191 {
1192   elf_section_t * s;
1193   clib_error_t * error;
1194
1195   error = elf_get_section_by_start_address (em, start_address, &s);
1196   if (error)
1197     {
1198       clib_error_report (error);
1199       return 0;
1200     }
1201
1202   if (section_index_result)
1203     *section_index_result = s->index;
1204
1205   return elf_get_section_contents (em, s->index, elt_size);
1206 }
1207
1208 static void elf_parse_dynamic (elf_main_t * em)
1209 {
1210   elf_section_t * s;
1211   elf64_dynamic_entry_t * e;
1212
1213   vec_foreach (s, em->sections)
1214     {
1215       switch (s->header.type)
1216         {
1217         case ELF_SECTION_DYNAMIC:
1218           add_dynamic_entries (em, s);
1219           break;
1220
1221         default:
1222           break;
1223         }
1224     }
1225
1226   em->dynamic_string_table_section_index = ~0;
1227   em->dynamic_string_table = 0;
1228
1229   vec_foreach (e, em->dynamic_entries)
1230     {
1231       switch (e->type)
1232         {
1233         case ELF_DYNAMIC_ENTRY_STRING_TABLE:
1234           ASSERT (vec_len (em->dynamic_string_table) == 0);
1235           em->dynamic_string_table
1236             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (u8),
1237                                                               &em->dynamic_string_table_section_index);
1238           break;
1239
1240         case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE:
1241           {
1242             elf_section_t * s;
1243             clib_error_t * error;
1244
1245             error = elf_get_section_by_start_address (em, e->data, &s);
1246             if (error)
1247               {
1248                 clib_error_report (error);
1249                 return;
1250               }
1251
1252             em->dynamic_symbol_table_section_index = s - em->sections;
1253           }
1254           break;
1255
1256         case ELF_DYNAMIC_ENTRY_VERSYM:
1257           em->versym
1258             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->versym[0]),
1259                                                               &em->versym_section_index);
1260           if (em->need_byte_swap)
1261             {
1262               uword i;
1263               for (i = 0; i < vec_len (em->versym); i++)
1264                 em->versym[i] = clib_byte_swap_u16 (em->versym[i]);
1265             }
1266           break;
1267
1268         case ELF_DYNAMIC_ENTRY_VERSION_NEED:
1269           em->verneed
1270             = elf_get_section_contents_with_starting_address (em, e->data, sizeof (em->verneed[0]),
1271                                                               &em->verneed_section_index);
1272           if (em->need_byte_swap)
1273             byte_swap_verneed (em, em->verneed);
1274           break;
1275
1276         default:
1277           break;
1278         }
1279     }
1280 }
1281
1282 #include <sys/types.h>
1283 #include <sys/stat.h>
1284 #include <fcntl.h>
1285
1286 clib_error_t * elf_read_file (elf_main_t * em, char * file_name)
1287 {
1288   int fd;
1289   struct stat fd_stat;
1290   uword mmap_length = 0;
1291   void * data = 0;
1292   clib_error_t * error = 0;
1293
1294   elf_main_init (em);
1295
1296   fd = open (file_name, 0);
1297   if (fd < 0)
1298     {
1299       error = clib_error_return_unix (0, "open `%s'", file_name);
1300       goto done;
1301     }
1302
1303   if (fstat (fd, &fd_stat) < 0)
1304     {
1305       error = clib_error_return_unix (0, "fstat `%s'", file_name);
1306       goto done;
1307     }
1308   mmap_length = fd_stat.st_size;
1309
1310   data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0);
1311   if (~pointer_to_uword (data) == 0)
1312     {
1313       error = clib_error_return_unix (0, "mmap `%s'", file_name);
1314       goto done;
1315     }
1316
1317   em->file_name = file_name;
1318
1319   error = elf_parse (em, data, mmap_length);
1320   if (error)
1321     goto done;
1322
1323   elf_parse_symbols (em);
1324   elf_parse_dynamic (em);
1325
1326   em->interpreter = elf_find_interpreter (em, data);
1327
1328   munmap (data, mmap_length);
1329   close (fd);
1330
1331   return /* no error */ 0;
1332
1333  done:
1334   elf_main_free (em);
1335   if (fd >= 0)
1336     close (fd);
1337   if (data)
1338     munmap (data, mmap_length);
1339   return error;
1340 }
1341
1342 typedef struct {
1343   u8 * new_table;
1344
1345   u8 * old_table;
1346
1347   uword * hash;
1348 } string_table_builder_t;
1349
1350 static u32 string_table_add_name (string_table_builder_t * b, u8 * n)
1351 {
1352   uword * p, i, j, l;
1353
1354   p = hash_get_mem (b->hash, n);
1355   if (p) return p[0];
1356
1357   l = strlen ((char *) n);
1358   i = vec_len (b->new_table);
1359   vec_add (b->new_table, n, l + 1);
1360
1361   for (j = 0; j <= l; j++)
1362     {
1363       if (j > 0)
1364         {
1365           p = hash_get_mem (b->hash, n + j);
1366
1367           /* Sub-string already in table? */
1368           if (p)
1369             continue;
1370         }
1371
1372       hash_set_mem (b->hash, n + j, i + j);
1373     }
1374
1375   return i;
1376 }
1377
1378 static u32 string_table_add_name_index (string_table_builder_t * b, u32 index)
1379 {
1380   u8 * n = b->old_table + index;
1381   return string_table_add_name (b, n);
1382 }
1383
1384 static void string_table_init (string_table_builder_t * b, u8 * old_table)
1385 {
1386   memset (b, 0, sizeof (b[0]));
1387   b->old_table = old_table;
1388   b->hash = hash_create_string (0, sizeof (uword));
1389 }
1390
1391 static u8 * string_table_done (string_table_builder_t * b)
1392 {
1393   hash_free (b->hash);
1394   return b->new_table;
1395 }
1396
1397 static void layout_sections (elf_main_t * em)
1398 {
1399   elf_section_t * s;
1400   u32 n_sections_with_changed_exec_address = 0;
1401   u32 * deferred_symbol_and_string_sections = 0;
1402   u32 n_deleted_sections = 0;
1403   int rebuild = 0;
1404
1405   /* Re-build section string table (sections may have been deleted). */
1406   if (rebuild)
1407     {
1408       u8 * st = 0;
1409
1410       vec_foreach (s, em->sections)
1411         {
1412           u8 * name;
1413           if (s->header.type == ~0)
1414             continue;
1415           name = elf_section_name (em, s);
1416           s->header.name = vec_len (st);
1417           vec_add (st, name, strlen ((char *) name) + 1);
1418         }
1419
1420       s = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1421
1422       vec_free (s->contents);
1423       s->contents = st;
1424     }
1425
1426   /* Re-build dynamic string table. */
1427   if (rebuild && em->dynamic_string_table_section_index != ~0)
1428     {
1429       string_table_builder_t b;
1430     
1431       string_table_init (&b, em->dynamic_string_table);
1432
1433       /* Add all dynamic symbols. */
1434       {
1435         elf_symbol_table_t * symtab;
1436         elf64_symbol_t * sym;
1437
1438         symtab = vec_elt_at_index (em->symbol_tables, em->dynamic_symbol_table_index);
1439         vec_foreach (sym, symtab->symbols)
1440           {
1441             u8 * name = elf_symbol_name (symtab, sym);
1442             sym->name = string_table_add_name (&b, name);
1443           }
1444
1445         set_symbol_table (em, em->dynamic_symbol_table_index);
1446       }
1447
1448       /* Add all dynamic entries. */
1449       {
1450         elf64_dynamic_entry_t * e;
1451
1452         vec_foreach (e, em->dynamic_entries)
1453           {
1454             switch (e->type)
1455               {
1456               case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY:
1457               case ELF_DYNAMIC_ENTRY_RPATH:
1458               case ELF_DYNAMIC_ENTRY_RUN_PATH:
1459                 e->data = string_table_add_name_index (&b, e->data);
1460                 break;
1461               }
1462           }
1463       }
1464
1465       /* Add all version needs. */
1466       if (vec_len (em->verneed) > 0)
1467         {
1468           elf_dynamic_version_need_union_t * n, * a;
1469
1470           n = em->verneed;
1471           while (1)
1472             {
1473               n->need.file_name_offset = string_table_add_name_index (&b, n->need.file_name_offset);
1474
1475               if (n->need.first_aux_offset != 0)
1476                 {
1477                   a = n + n->need.first_aux_offset / sizeof (n[0]);
1478                   while (1)
1479                     {
1480                       a->aux.name = string_table_add_name_index (&b, a->aux.name);
1481                       if (a->aux.next_offset == 0)
1482                         break;
1483                       a += a->aux.next_offset / sizeof (a[0]);
1484                     }
1485                 }
1486
1487               if (n->need.next_offset == 0)
1488                 break;
1489
1490               n += n->need.next_offset / sizeof (n[0]);
1491             }
1492
1493           set_dynamic_verneed (em);
1494         }
1495
1496       s = vec_elt_at_index (em->sections, em->dynamic_string_table_section_index);
1497
1498       vec_free (s->contents);
1499       s->contents = string_table_done (&b);
1500     }
1501
1502   /* Figure file offsets and exec addresses for sections. */
1503   {
1504     u64 exec_address = 0, file_offset = 0;
1505     u64 file_size, align_size;
1506
1507     vec_foreach (s, em->sections)
1508       {
1509         /* Ignore deleted and unused sections. */
1510         switch (s->header.type)
1511           {
1512           case ~0:
1513             n_deleted_sections++;
1514           case ELF_SECTION_UNUSED:
1515             continue;
1516
1517           case ELF_SECTION_STRING_TABLE:
1518           case ELF_SECTION_SYMBOL_TABLE:
1519             if (! (s->index == em->dynamic_string_table_section_index
1520                    || s->index == em->file_header.section_header_string_table_index))
1521               {
1522                 vec_add1 (deferred_symbol_and_string_sections, s->index);
1523                 continue;
1524               }
1525             break;
1526
1527           default:
1528             break;
1529           }
1530
1531         exec_address = round_pow2_u64 (exec_address, s->header.align);
1532
1533         /* Put sections we added at end of file. */
1534         if (s->header.file_offset == ~0)
1535           s->header.file_offset = file_offset;
1536
1537         /* Follow gaps in original file. */
1538         if (s->header.exec_address > exec_address)
1539           {
1540             exec_address = s->header.exec_address;
1541             file_offset = s->header.file_offset;
1542           }
1543
1544         if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1545           {
1546             s->exec_address_change = exec_address - s->header.exec_address;
1547             n_sections_with_changed_exec_address += s->exec_address_change != 0;
1548             s->header.exec_address = exec_address;
1549           }
1550
1551         if (s->header.type == ELF_SECTION_NO_BITS)
1552           file_size = s->header.file_size;
1553         else
1554           file_size = vec_len (s->contents);
1555
1556         {
1557           u64 align;
1558
1559           if (s + 1 >= vec_end (em->sections))
1560             align = 16;
1561           else if (s[1].header.type == ELF_SECTION_NO_BITS)
1562             align = 8;
1563           else
1564             align = s[1].header.align;
1565
1566           if (s->header.flags & ELF_SECTION_FLAG_ALLOC)
1567             {
1568               u64 v = round_pow2_u64 (exec_address + file_size, align);
1569               align_size = v - exec_address;
1570             }
1571           else
1572             {
1573               u64 v = round_pow2_u64 (file_offset + file_size, align);
1574               align_size = v - file_offset;
1575             }
1576         }
1577
1578         s->header.file_offset = file_offset;
1579         s->header.file_size = file_size;
1580         s->align_size = align_size;
1581
1582         if (s->header.type != ELF_SECTION_NO_BITS)
1583           file_offset += align_size;
1584         exec_address += align_size;
1585       }
1586
1587     /* Section headers go after last section but before symbol/string
1588        tables. */
1589     {
1590       elf64_file_header_t * fh = &em->file_header;
1591
1592       fh->section_header_file_offset = file_offset;
1593       fh->section_header_count = vec_len (em->sections) - n_deleted_sections;
1594       file_offset += fh->section_header_count * fh->section_header_size;
1595     }
1596
1597     {
1598       int i;
1599       for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++)
1600         {
1601           s = vec_elt_at_index (em->sections, deferred_symbol_and_string_sections[i]);
1602
1603           s->header.file_offset = file_offset;
1604           s->header.file_size = vec_len (s->contents);
1605
1606           align_size = round_pow2 (vec_len (s->contents), 16);
1607           s->align_size = align_size;
1608           file_offset += align_size;
1609         }
1610       vec_free (deferred_symbol_and_string_sections);
1611     }
1612   }
1613
1614   /* Update dynamic entries now that sections have been assigned
1615      possibly new addresses. */
1616   if (rebuild)
1617     elf_set_dynamic_entries (em);
1618
1619   /* Update segments for changed section addresses. */
1620   {
1621     elf_segment_t * g;
1622     uword si;
1623
1624     vec_foreach (g, em->segments)
1625       {
1626         u64 s_lo, s_hi, f_lo = 0;
1627         u32 n_sections = 0;
1628
1629         if (g->header.memory_size == 0)
1630           continue;
1631
1632         s_lo = s_hi = 0;
1633         clib_bitmap_foreach (si, g->section_index_bitmap, ({
1634           u64 lo, hi;
1635
1636           s = vec_elt_at_index (em->sections, si);
1637           lo = s->header.exec_address;
1638           hi = lo + s->align_size;
1639           if (n_sections == 0)
1640             {
1641               s_lo = lo;
1642               s_hi = hi;
1643               f_lo = s->header.file_offset;
1644               n_sections++;
1645             }
1646           else
1647             {
1648               if (lo < s_lo)
1649                 {
1650                   s_lo = lo;
1651                   f_lo = s->header.file_offset;
1652                 }
1653               if (hi > s_hi)
1654                 s_hi = hi;
1655             }
1656         }));
1657
1658         if (n_sections == 0)
1659           continue;
1660
1661         /* File offset zero includes ELF headers/segment headers.
1662            Don't change that. */
1663         if (g->header.file_offset == 0
1664             && g->header.type == ELF_SEGMENT_LOAD)
1665           {
1666             s_lo = g->header.virtual_address;
1667             f_lo = g->header.file_offset;
1668           }
1669
1670         g->header.virtual_address = s_lo;
1671         g->header.physical_address = s_lo;
1672         g->header.file_offset = f_lo;
1673         g->header.memory_size = s_hi - s_lo;
1674       }
1675   }
1676 }
1677
1678 clib_error_t * elf_write_file (elf_main_t * em, char * file_name)
1679 {
1680   int fd;
1681   FILE * f;
1682   clib_error_t * error = 0;
1683
1684   fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755);
1685   if (fd < 0)
1686     return clib_error_return_unix (0, "open `%s'", file_name);
1687
1688   f = fdopen (fd, "w");
1689
1690   /* Section contents may have changed.  So, we need to update
1691      stuff to reflect this. */
1692   layout_sections (em);
1693
1694   /* Write first header. */
1695   {
1696     elf_first_header_t h = em->first_header;
1697
1698     elf_swap_first_header (em, &h);
1699     if (fwrite (&h, sizeof (h), 1, f) != 1)
1700       {
1701         error = clib_error_return_unix (0, "write first header");
1702         goto error;
1703       }
1704   }
1705
1706   /* Write file header. */
1707   {
1708     elf64_file_header_t h = em->file_header;
1709
1710     /* Segment headers are after first header. */
1711     h.segment_header_file_offset = sizeof (elf_first_header_t);
1712     if (em->first_header.file_class == ELF_64BIT)
1713       h.segment_header_file_offset += sizeof (elf64_file_header_t);
1714     else
1715       h.segment_header_file_offset += sizeof (elf32_file_header_t);
1716
1717     if (em->first_header.file_class == ELF_64BIT)
1718       {
1719 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1720         foreach_elf64_file_header;
1721 #undef _
1722
1723       if (fwrite (&h, sizeof (h), 1, f) != 1)
1724         {
1725           error = clib_error_return_unix (0, "write file header");
1726           goto error;
1727         }
1728     }
1729   else
1730     {
1731       elf32_file_header_t h32;
1732
1733 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1734       foreach_elf32_file_header;
1735 #undef _
1736
1737       if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1738         {
1739           error = clib_error_return_unix (0, "write file header");
1740           goto error;
1741         }
1742     }
1743   }
1744
1745   /* Write segment headers. */
1746   {
1747     elf_segment_t * s;
1748
1749     vec_foreach (s, em->segments)
1750       {
1751         elf64_segment_header_t h;
1752
1753         if (s->header.type == ~0)
1754           continue;
1755
1756         h = s->header;
1757
1758         if (em->first_header.file_class == ELF_64BIT)
1759           {
1760 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1761             foreach_elf64_segment_header;
1762 #undef _
1763             
1764             if (fwrite (&h, sizeof (h), 1, f) != 1)
1765               {
1766                 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1767                 goto error;
1768               }
1769           }
1770         else
1771           {
1772             elf32_segment_header_t h32;
1773
1774 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1775             foreach_elf32_segment_header;
1776 #undef _
1777
1778             if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1779               {
1780                 error = clib_error_return_unix (0, "write segment header %U", format_elf_segment, em, s);
1781                 goto error;
1782               }
1783           }
1784       }
1785   }
1786
1787   /* Write contents for all sections. */
1788   {
1789     elf_section_t * s;
1790
1791     vec_foreach (s, em->sections)
1792       {
1793         if (s->header.file_size == 0)
1794           continue;
1795
1796         if (fseek (f, s->header.file_offset, SEEK_SET) < 0)
1797           return clib_error_return_unix (0, "fseek 0x%Lx", s->header.file_offset);
1798
1799         if (s->header.type == ELF_SECTION_NO_BITS)
1800           /* don't write for .bss sections */;
1801         else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1)
1802           {
1803             error = clib_error_return_unix (0, "write %s section contents", elf_section_name (em, s));
1804             goto error;
1805           }
1806       }
1807
1808     /* Finally write section headers. */
1809     if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0)
1810       return clib_error_return_unix (0, "fseek 0x%Lx", em->file_header.section_header_file_offset);
1811
1812     vec_foreach (s, em->sections)
1813       {
1814         elf64_section_header_t h;
1815
1816         if (s->header.type == ~0)
1817           continue;
1818
1819         h = s->header;
1820
1821         if (em->first_header.file_class == ELF_64BIT)
1822           {
1823 #define _(t,field) h.field = elf_swap_##t (em, h.field);
1824             foreach_elf64_section_header;
1825 #undef _
1826             
1827             if (fwrite (&h, sizeof (h), 1, f) != 1)
1828               {
1829                 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1830                 goto error;
1831               }
1832           }
1833         else
1834           {
1835             elf32_section_header_t h32;
1836
1837 #define _(t,field) h32.field = elf_swap_##t (em, h.field);
1838             foreach_elf32_section_header;
1839 #undef _
1840
1841             if (fwrite (&h32, sizeof (h32), 1, f) != 1)
1842               {
1843                 error = clib_error_return_unix (0, "write %s section header", elf_section_name (em, s));
1844                 goto error;
1845               }
1846           }
1847       }
1848   }
1849
1850  error:
1851   fclose (f);
1852   return error;
1853 }
1854
1855 clib_error_t * elf_delete_named_section (elf_main_t * em, char * section_name)
1856 {
1857   elf_section_t * s;
1858   clib_error_t * error;
1859
1860   error = elf_get_section_by_name (em, section_name, &s);
1861   if (error)
1862     return error;
1863   
1864   s->header.type = ~0;
1865
1866   return 0;
1867 }
1868
1869 void
1870 elf_create_section_with_contents (elf_main_t * em,
1871                                   char * section_name,
1872                                   elf64_section_header_t * header,
1873                                   void * contents,
1874                                   uword n_content_bytes)
1875 {
1876   elf_section_t * s, * sts;
1877   u8 * st, * c;
1878   uword * p, is_new_section;
1879
1880   /* See if section already exists with given name.
1881      If so, just replace contents. */
1882   is_new_section = 0;
1883   if ((p = hash_get_mem (em->section_by_name, section_name)))
1884     {
1885       s = vec_elt_at_index (em->sections, p[0]);
1886       _vec_len (s->contents) = 0;
1887       c = s->contents;
1888     }
1889   else
1890     {
1891       vec_add2 (em->sections, s, 1);
1892       is_new_section = 1;
1893       c = 0;
1894     }
1895
1896   sts = vec_elt_at_index (em->sections, em->file_header.section_header_string_table_index);
1897   st = sts->contents;
1898
1899   s->header = header[0];
1900
1901   s->header.file_offset = ~0;
1902   s->header.file_size = n_content_bytes;
1903   s->index = s - em->sections;
1904
1905   /* Add name to string table. */
1906   s->header.name = vec_len (st);
1907   vec_add (st, section_name, strlen (section_name));
1908   vec_add1 (st, 0);
1909   sts->contents = st;
1910
1911   vec_resize (c, n_content_bytes);
1912   memcpy (c, contents, n_content_bytes);
1913   s->contents = c;
1914
1915   em->file_header.section_header_count += is_new_section && s->header.type != ~0;
1916 }
1917
1918 uword elf_delete_segment_with_type (elf_main_t * em, elf_segment_type_t segment_type)
1919 {
1920   uword n_deleted = 0;
1921   elf_segment_t * s;
1922
1923   vec_foreach (s, em->segments)
1924     if (s->header.type == segment_type)
1925       {
1926         s->header.type = ~0;
1927         n_deleted += 1;
1928       }
1929
1930   ASSERT (em->file_header.segment_header_count >= n_deleted);
1931   em->file_header.segment_header_count -= n_deleted;
1932
1933   return n_deleted;
1934 }
1935
1936 #endif /* CLIB_UNIX */