LCOV - code coverage report
Current view: top level - vppinfra - elf.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 201 842 23.9 %
Date: 2023-07-05 22:20:52 Functions: 15 50 30.0 %

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

Generated by: LCOV version 1.14