LCOV - code coverage report
Current view: top level - libasm - asm_end.c (source / functions) Hit Total Coverage
Test: elfutils-0.176 Lines: 234 259 90.3 %
Date: 2019-02-15 17:57:54 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Finalize operations on the assembler context, free all resources.
       2             :    Copyright (C) 2002, 2003, 2005, 2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of either
       8             : 
       9             :      * the GNU Lesser General Public License as published by the Free
      10             :        Software Foundation; either version 3 of the License, or (at
      11             :        your option) any later version
      12             : 
      13             :    or
      14             : 
      15             :      * the GNU General Public License as published by the Free
      16             :        Software Foundation; either version 2 of the License, or (at
      17             :        your option) any later version
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    elfutils is distributed in the hope that it will be useful, but
      22             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    General Public License for more details.
      25             : 
      26             :    You should have received copies of the GNU General Public License and
      27             :    the GNU Lesser General Public License along with this program.  If
      28             :    not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : # include <config.h>
      32             : #endif
      33             : 
      34             : #include <assert.h>
      35             : #include <libintl.h>
      36             : #include <stdio.h>
      37             : #include <stdlib.h>
      38             : #include <string.h>
      39             : #include <unistd.h>
      40             : #include <sys/stat.h>
      41             : 
      42             : #include <libasmP.h>
      43             : #include <libelf.h>
      44             : #include <system.h>
      45             : 
      46             : 
      47             : static int
      48           0 : text_end (AsmCtx_t *ctx __attribute__ ((unused)))
      49             : {
      50           0 :   if (fclose (ctx->out.file) != 0)
      51             :     {
      52           0 :       __libasm_seterrno (ASM_E_IOERROR);
      53           0 :       return -1;
      54             :     }
      55             : 
      56             :   return 0;
      57             : }
      58             : 
      59             : 
      60             : static int
      61           9 : binary_end (AsmCtx_t *ctx)
      62             : {
      63           9 :   void *symtab = NULL;
      64           9 :   Dwelf_Strent *symscn_strent = NULL;
      65           9 :   Dwelf_Strent *strscn_strent = NULL;
      66           9 :   Dwelf_Strent *xndxscn_strent = NULL;
      67             :   Elf_Scn *shstrscn;
      68             :   Dwelf_Strent *shstrscn_strent;
      69             :   size_t shstrscnndx;
      70           9 :   size_t symscnndx = 0;
      71           9 :   size_t strscnndx = 0;
      72           9 :   size_t xndxscnndx = 0;
      73             :   Elf_Data *data;
      74             :   Elf_Data *shstrtabdata;
      75           9 :   Elf_Data *strtabdata = NULL;
      76           9 :   Elf_Data *xndxdata = NULL;
      77             :   GElf_Shdr shdr_mem;
      78             :   GElf_Shdr *shdr;
      79             :   GElf_Ehdr ehdr_mem;
      80             :   GElf_Ehdr *ehdr;
      81             :   AsmScn_t *asmscn;
      82           9 :   int result = 0;
      83             : 
      84             :   /* Iterate over the created sections and compute the offsets of the
      85             :      various subsections and fill in the content.  */
      86      176014 :   for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
      87             :     {
      88             : #if 0
      89             :       Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
      90             : #else
      91      176005 :       Elf_Scn *scn = asmscn->data.main.scn;
      92             : #endif
      93      176005 :       off_t offset = 0;
      94      176005 :       AsmScn_t *asmsubscn = asmscn;
      95             : 
      96             :       do
      97             :         {
      98      176007 :           struct AsmData *content = asmsubscn->content;
      99      176007 :           bool first = true;
     100             : 
     101      352014 :           offset = ((offset + asmsubscn->max_align - 1)
     102      176007 :                     & ~(asmsubscn->max_align - 1));
     103             : 
     104             :           /* Update the offset for this subsection.  This field now
     105             :              stores the offset of the first by in this subsection.  */
     106      176007 :           asmsubscn->offset = offset;
     107             : 
     108             :           /* Note that the content list is circular.  */
     109      176007 :           if (content != NULL)
     110             :             do
     111             :               {
     112      176005 :                 Elf_Data *newdata = elf_newdata (scn);
     113             : 
     114      176005 :                 if (newdata == NULL)
     115             :                   {
     116           0 :                     __libasm_seterrno (ASM_E_LIBELF);
     117           0 :                     return -1;
     118             :                   }
     119             : 
     120      176005 :                 newdata->d_buf = content->data;
     121      176005 :                 newdata->d_type = ELF_T_BYTE;
     122      176005 :                 newdata->d_size = content->len;
     123      176005 :                 newdata->d_off = offset;
     124      176005 :                 newdata->d_align = first ? asmsubscn->max_align : 1;
     125             : 
     126      176005 :                 offset += content->len;
     127             :               }
     128      176005 :             while ((content = content->next) != asmsubscn->content);
     129             :         }
     130      176007 :       while ((asmsubscn = asmsubscn->subnext) != NULL);
     131             :     }
     132             : 
     133             : 
     134             :   /* Create the symbol table if necessary.  */
     135           9 :   if (ctx->nsymbol_tab > 0)
     136             :     {
     137             :       /* Create the symbol table and string table section names.  */
     138           5 :       symscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".symtab", 8);
     139           5 :       strscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".strtab", 8);
     140             : 
     141             :       /* Create the symbol string table section.  */
     142           5 :       Elf_Scn *strscn = elf_newscn (ctx->out.elf);
     143           5 :       strtabdata = elf_newdata (strscn);
     144           5 :       shdr = gelf_getshdr (strscn, &shdr_mem);
     145           5 :       if (strtabdata == NULL || shdr == NULL)
     146             :         {
     147           0 :           __libasm_seterrno (ASM_E_LIBELF);
     148           0 :           return -1;
     149             :         }
     150           5 :       strscnndx = elf_ndxscn (strscn);
     151             : 
     152           5 :       dwelf_strtab_finalize (ctx->symbol_strtab, strtabdata);
     153             : 
     154           5 :       shdr->sh_type = SHT_STRTAB;
     155           5 :       assert (shdr->sh_entsize == 0);
     156             : 
     157           5 :       (void) gelf_update_shdr (strscn, shdr);
     158             : 
     159             :       /* Create the symbol table section.  */
     160           5 :       Elf_Scn *symscn = elf_newscn (ctx->out.elf);
     161           5 :       data = elf_newdata (symscn);
     162           5 :       shdr = gelf_getshdr (symscn, &shdr_mem);
     163           5 :       if (data == NULL || shdr == NULL)
     164             :         {
     165           0 :           __libasm_seterrno (ASM_E_LIBELF);
     166           0 :           return -1;
     167             :         }
     168           5 :       symscnndx = elf_ndxscn (symscn);
     169             : 
     170             :       /* We know how many symbols there will be in the symbol table.  */
     171           5 :       data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
     172           5 :                                  ctx->nsymbol_tab + 1, EV_CURRENT);
     173           5 :       symtab = malloc (data->d_size);
     174           5 :       if (symtab == NULL)
     175             :         return -1;
     176           5 :       data->d_buf = symtab;
     177           5 :       data->d_type = ELF_T_SYM;
     178           5 :       data->d_off = 0;
     179             : 
     180             :       /* Clear the first entry.  */
     181             :       GElf_Sym syment;
     182           5 :       memset (&syment, '\0', sizeof (syment));
     183           5 :       (void) gelf_update_sym (data, 0, &syment);
     184             : 
     185             :       /* Iterate over the symbol table.  */
     186           5 :       void *runp = NULL;
     187           5 :       int ptr_local = 1;        /* Start with index 1; zero remains unused.  */
     188           5 :       int ptr_nonlocal = ctx->nsymbol_tab;
     189           5 :       uint32_t *xshndx = NULL;
     190             :       AsmSym_t *sym;
     191       88015 :       while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
     192       88005 :         if (asm_emit_symbol_p (dwelf_strent_str (sym->strent)))
     193             :           {
     194       88005 :             assert (ptr_local <= ptr_nonlocal);
     195             : 
     196       88005 :             syment.st_name = dwelf_strent_off (sym->strent);
     197       88005 :             syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
     198       88005 :             syment.st_other = 0;
     199       88005 :             syment.st_value = sym->scn->offset + sym->offset;
     200       88005 :             syment.st_size = sym->size;
     201             : 
     202             :             /* Add local symbols at the beginning, the other from
     203             :                the end.  */
     204       88005 :             int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
     205             : 
     206             :             /* Determine the section index.  We have to handle the
     207             :                overflow correctly.  */
     208      176010 :             Elf_Scn *scn = (sym->scn->subsection_id == 0
     209             :                             ? sym->scn->data.main.scn
     210       88005 :                             : sym->scn->data.up->data.main.scn);
     211             : 
     212             :             Elf32_Word ndx;
     213       88005 :             if (unlikely (scn == ASM_ABS_SCN))
     214             :               ndx = SHN_ABS;
     215       88004 :             else if (unlikely (scn == ASM_COM_SCN))
     216             :               ndx = SHN_COMMON;
     217       88003 :             else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
     218             :               {
     219         961 :                 if (unlikely (xshndx == NULL))
     220             :                   {
     221             :                     /* The extended section index section does not yet
     222             :                        exist.  */
     223             :                     Elf_Scn *xndxscn;
     224             : 
     225           2 :                     xndxscn = elf_newscn (ctx->out.elf);
     226           2 :                     xndxdata = elf_newdata (xndxscn);
     227           2 :                     shdr = gelf_getshdr (xndxscn, &shdr_mem);
     228           2 :                     if (xndxdata == NULL || shdr == NULL)
     229             :                       {
     230           0 :                         __libasm_seterrno (ASM_E_LIBELF);
     231           0 :                         return -1;
     232             :                       }
     233           2 :                     xndxscnndx = elf_ndxscn (xndxscn);
     234             : 
     235           2 :                     shdr->sh_type = SHT_SYMTAB_SHNDX;
     236           2 :                     shdr->sh_entsize = sizeof (Elf32_Word);
     237           2 :                     shdr->sh_addralign = sizeof (Elf32_Word);
     238           2 :                     shdr->sh_link = symscnndx;
     239             : 
     240           2 :                     (void) gelf_update_shdr (xndxscn, shdr);
     241             : 
     242           2 :                     xndxscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
     243             :                                                            ".symtab_shndx",
     244             :                                                            14);
     245             : 
     246             :                     /* Note that using 'elf32_fsize' instead of
     247             :                        'gelf_fsize' here is correct.  */
     248           2 :                     xndxdata->d_size = elf32_fsize (ELF_T_WORD,
     249           2 :                                                     ctx->nsymbol_tab + 1,
     250             :                                                     EV_CURRENT);
     251           2 :                     xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
     252           2 :                     if (xshndx == NULL)
     253             :                       return -1;
     254             :                     /* Using ELF_T_WORD here relies on the fact that the
     255             :                        32- and 64-bit types are the same size.  */
     256           2 :                     xndxdata->d_type = ELF_T_WORD;
     257           2 :                     xndxdata->d_off = 0;
     258             :                   }
     259             : 
     260             :                 /* Store the real section index in the extended setion
     261             :                    index table.  */
     262         961 :                 assert ((size_t) ptr < ctx->nsymbol_tab + 1);
     263         961 :                 xshndx[ptr] = ndx;
     264             : 
     265             :                 /* And signal that this happened.  */
     266         961 :                 ndx = SHN_XINDEX;
     267             :               }
     268       88005 :             syment.st_shndx = ndx;
     269             : 
     270             :             /* Remember where we put the symbol.  */
     271       88005 :             sym->symidx = ptr;
     272             : 
     273       88005 :             (void) gelf_update_sym (data, ptr, &syment);
     274             :           }
     275             : 
     276           5 :       assert (ptr_local == ptr_nonlocal + 1);
     277             : 
     278           5 :       shdr->sh_type = SHT_SYMTAB;
     279           5 :       shdr->sh_link = strscnndx;
     280           5 :       shdr->sh_info = ptr_local;
     281           5 :       shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
     282           5 :       shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
     283             :                                        EV_CURRENT);
     284             : 
     285           5 :       (void) gelf_update_shdr (symscn, shdr);
     286             :     }
     287             : 
     288             : 
     289             :   /* Create the section header string table section and fill in the
     290             :      references in the section headers.  */
     291           9 :   shstrscn = elf_newscn (ctx->out.elf);
     292           9 :   shstrtabdata = elf_newdata (shstrscn);
     293           9 :   shdr = gelf_getshdr (shstrscn, &shdr_mem);
     294           9 :   if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
     295             :     {
     296           0 :       __libasm_seterrno (ASM_E_LIBELF);
     297           0 :       return -1;
     298             :     }
     299             : 
     300             : 
     301             :   /* Add the name of the section header string table.  */
     302           9 :   shstrscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
     303             :                                           ".shstrtab", 10);
     304             : 
     305           9 :   dwelf_strtab_finalize (ctx->section_strtab, shstrtabdata);
     306             : 
     307           9 :   shdr->sh_type = SHT_STRTAB;
     308           9 :   assert (shdr->sh_entsize == 0);
     309           9 :   shdr->sh_name = dwelf_strent_off (shstrscn_strent);
     310             : 
     311           9 :   (void) gelf_update_shdr (shstrscn, shdr);
     312             : 
     313             : 
     314             :   /* Create the section groups.  */
     315           9 :   if (ctx->groups != NULL)
     316             :     {
     317           1 :       AsmScnGrp_t *runp = ctx->groups->next;
     318             : 
     319             :       do
     320             :         {
     321             :           Elf_Scn *scn;
     322             :           Elf32_Word *grpdata;
     323             : 
     324       22000 :           scn = runp->scn;
     325       22000 :           assert (scn != NULL);
     326       22000 :           shdr = gelf_getshdr (scn, &shdr_mem);
     327       22000 :           assert (shdr != NULL);
     328             : 
     329       22000 :           data = elf_newdata (scn);
     330       22000 :           if (data == NULL)
     331             :             {
     332           0 :               __libasm_seterrno (ASM_E_LIBELF);
     333           0 :               return -1;
     334             :             }
     335             : 
     336             :           /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
     337             :              here.  */
     338       22000 :           data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
     339             :                                       EV_CURRENT);
     340       22000 :           grpdata = data->d_buf = malloc (data->d_size);
     341       22000 :           if (grpdata == NULL)
     342             :             return -1;
     343       22000 :           data->d_type = ELF_T_WORD;
     344       22000 :           data->d_off = 0;
     345       22000 :           data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
     346             : 
     347             :           /* The first word of the section is filled with the flag word.  */
     348       22000 :           *grpdata++ = runp->flags;
     349             : 
     350       22000 :           if (runp->members != NULL)
     351             :             {
     352       22000 :               AsmScn_t *member = runp->members->data.main.next_in_group;
     353             : 
     354             :               do
     355             :                 {
     356             :                   /* Only sections, not subsections, can be registered
     357             :                      as member of a group.  The subsections get
     358             :                      automatically included.  */
     359       44000 :                   assert (member->subsection_id == 0);
     360             : 
     361       44000 :                   *grpdata++ = elf_ndxscn (member->data.main.scn);
     362             :                 }
     363       44000 :               while ((member = member->data.main.next_in_group)
     364       44000 :                      != runp->members->data.main.next_in_group);
     365             :             }
     366             : 
     367             :           /* Construct the section header.  */
     368       22000 :           shdr->sh_name = dwelf_strent_off (runp->strent);
     369       22000 :           shdr->sh_type = SHT_GROUP;
     370       22000 :           shdr->sh_flags = 0;
     371       22000 :           shdr->sh_link = symscnndx;
     372             :           /* If the user did not specify a signature we use the initial
     373             :              empty symbol in the symbol table as the signature.  */
     374       44000 :           shdr->sh_info = (runp->signature != NULL
     375       22000 :                            ? runp->signature->symidx : 0);
     376             : 
     377       22000 :           (void) gelf_update_shdr (scn, shdr);
     378             :         }
     379       22000 :       while ((runp = runp->next) != ctx->groups->next);
     380             :     }
     381             : 
     382             : 
     383             :   /* Add the name to the symbol section.  */
     384           9 :   if (likely (symscnndx != 0))
     385             :     {
     386           5 :       Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
     387             : 
     388           5 :       shdr = gelf_getshdr (scn, &shdr_mem);
     389             : 
     390           5 :       shdr->sh_name = dwelf_strent_off (symscn_strent);
     391             : 
     392           5 :       (void) gelf_update_shdr (scn, shdr);
     393             : 
     394             : 
     395             :       /* Add the name to the string section.  */
     396           5 :       assert (strscnndx != 0);
     397           5 :       scn = elf_getscn (ctx->out.elf, strscnndx);
     398             : 
     399           5 :       shdr = gelf_getshdr (scn, &shdr_mem);
     400             : 
     401           5 :       shdr->sh_name = dwelf_strent_off (strscn_strent);
     402             : 
     403           5 :       (void) gelf_update_shdr (scn, shdr);
     404             : 
     405             : 
     406             :       /* Add the name to the extended symbol index section.  */
     407           5 :       if (xndxscnndx != 0)
     408             :         {
     409           2 :           scn = elf_getscn (ctx->out.elf, xndxscnndx);
     410             : 
     411           2 :           shdr = gelf_getshdr (scn, &shdr_mem);
     412             : 
     413           2 :           shdr->sh_name = dwelf_strent_off (xndxscn_strent);
     414             : 
     415           2 :           (void) gelf_update_shdr (scn, shdr);
     416             :         }
     417             :     }
     418             : 
     419             : 
     420             :   /* Iterate over the created sections and fill in the names.  */
     421      176014 :   for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
     422             :     {
     423      176005 :       shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
     424             :       /* This better should not fail.  */
     425      176005 :       assert (shdr != NULL);
     426             : 
     427      176005 :       shdr->sh_name = dwelf_strent_off (asmscn->data.main.strent);
     428             : 
     429             :       /* We now know the maximum alignment.  */
     430      176005 :       shdr->sh_addralign = asmscn->max_align;
     431             : 
     432      176005 :       (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
     433             :     }
     434             : 
     435             :   /* Put the reference to the section header string table in the ELF
     436             :      header.  */
     437           9 :   ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
     438           9 :   assert (ehdr != NULL);
     439             : 
     440           9 :   shstrscnndx = elf_ndxscn (shstrscn);
     441           9 :   if (unlikely (shstrscnndx > SHN_HIRESERVE)
     442           6 :       || unlikely (shstrscnndx == SHN_XINDEX))
     443           3 :     {
     444             :       /* The index of the section header string sectio is too large.  */
     445           3 :       Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
     446             : 
     447             :       /* Get the header for the zeroth section.  */
     448           3 :       shdr = gelf_getshdr (scn, &shdr_mem);
     449             :       /* This better does not fail.  */
     450           3 :       assert (shdr != NULL);
     451             : 
     452             :       /* The sh_link field of the zeroth section header contains the value.  */
     453           3 :       shdr->sh_link = shstrscnndx;
     454             : 
     455           3 :       (void) gelf_update_shdr (scn, shdr);
     456             : 
     457             :       /* This is the sign for the overflow.  */
     458           3 :       ehdr->e_shstrndx = SHN_XINDEX;
     459             :     }
     460             :   else
     461           6 :     ehdr->e_shstrndx = elf_ndxscn (shstrscn);
     462             : 
     463           9 :   gelf_update_ehdr (ctx->out.elf, ehdr);
     464             : 
     465             :   /* Write out the ELF file.  */
     466           9 :   if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP) < 0))
     467             :     {
     468           0 :       __libasm_seterrno (ASM_E_LIBELF);
     469           0 :       result = -1;
     470             :     }
     471             : 
     472             :   /* We do not need the section header and symbol string tables anymore.  */
     473           9 :   free (shstrtabdata->d_buf);
     474           9 :   if (strtabdata != NULL)
     475           5 :     free (strtabdata->d_buf);
     476             :   /* We might have allocated the extended symbol table index.  */
     477           9 :   if (xndxdata != NULL)
     478           2 :     free (xndxdata->d_buf);
     479             : 
     480             :   /* Free section groups memory.  */
     481           9 :   AsmScnGrp_t *scngrp = ctx->groups;
     482           9 :   if (scngrp != NULL)
     483             :     do
     484       22000 :       free (elf_getdata (scngrp->scn, NULL)->d_buf);
     485       22000 :     while ((scngrp = scngrp->next) != ctx->groups);
     486             : 
     487             :   /* Finalize the ELF handling.  */
     488           9 :   if (unlikely (elf_end (ctx->out.elf)) != 0)
     489             :     {
     490           0 :       __libasm_seterrno (ASM_E_LIBELF);
     491           0 :       result = -1;
     492             :     }
     493             : 
     494             :   /* Free the temporary resources.  */
     495           9 :   free (symtab);
     496             : 
     497           9 :   return result;
     498             : }
     499             : 
     500             : 
     501             : int
     502           9 : asm_end (AsmCtx_t *ctx)
     503             : {
     504             :   int result;
     505             : 
     506           9 :   if (ctx == NULL)
     507             :     /* Something went wrong earlier.  */
     508             :     return -1;
     509             : 
     510           9 :   result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
     511           9 :   if (result != 0)
     512             :     return result;
     513             : 
     514             :   /* Make the new file globally readable and user/group-writable.  */
     515           9 :   if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
     516             :     {
     517           0 :       __libasm_seterrno (ASM_E_CANNOT_CHMOD);
     518           0 :       return -1;
     519             :     }
     520             : 
     521             :   /* Rename output file.  */
     522           9 :   if (rename (ctx->tmp_fname, ctx->fname) != 0)
     523             :     {
     524           0 :       __libasm_seterrno (ASM_E_CANNOT_RENAME);
     525           0 :       return -1;
     526             :     }
     527             : 
     528             :   /* Free the resources.  */
     529           9 :   __libasm_finictx (ctx);
     530             : 
     531           9 :   return 0;
     532             : }
     533             : 
     534             : 
     535             : static void
     536      176007 : free_section (AsmScn_t *scnp)
     537             : {
     538             :   void *oldp;
     539             : 
     540      176007 :   if (scnp->subnext != NULL)
     541           2 :     free_section (scnp->subnext);
     542             : 
     543      176007 :   struct AsmData *data = scnp->content;
     544      176007 :   if (data != NULL)
     545             :     do
     546             :       {
     547      176005 :         oldp = data;
     548      176005 :         data = data->next;
     549      176005 :         free (oldp);
     550             :       }
     551      176005 :     while (oldp != scnp->content);
     552             : 
     553      176007 :   free (scnp);
     554      176007 : }
     555             : 
     556             : 
     557             : void
     558             : internal_function
     559           9 : __libasm_finictx (AsmCtx_t *ctx)
     560             : {
     561             :   /* Iterate through section table and free individual entries.  */
     562           9 :   AsmScn_t *scn = ctx->section_list;
     563      176023 :   while (scn != NULL)
     564             :     {
     565      176005 :       AsmScn_t *oldp = scn;
     566      176005 :       scn = scn->allnext;
     567      176005 :       free_section (oldp);
     568             :     }
     569             : 
     570             :   /* Free the resources of the symbol table.  */
     571           9 :   void *runp = NULL;
     572             :   AsmSym_t *sym;
     573       88023 :   while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
     574       88005 :     free (sym);
     575           9 :   asm_symbol_tab_free (&ctx->symbol_tab);
     576             : 
     577             : 
     578             :   /* Free section groups.  */
     579           9 :   AsmScnGrp_t *scngrp = ctx->groups;
     580           9 :   if (scngrp != NULL)
     581             :     do
     582             :       {
     583       22000 :         AsmScnGrp_t *oldp = scngrp;
     584             : 
     585       22000 :         scngrp = scngrp->next;
     586       22000 :         free (oldp);
     587             :       }
     588       22000 :     while (scngrp != ctx->groups);
     589             : 
     590             : 
     591           9 :   if (unlikely (ctx->textp))
     592             :     {
     593             :       /* Close the stream.  */
     594           0 :       fclose (ctx->out.file);
     595             :     }
     596             :   else
     597             :     {
     598             :       /* Close the output file.  */
     599             :       /* XXX We should test for errors here but what would we do if we'd
     600             :          find any.  */
     601           9 :       (void) close (ctx->fd);
     602             : 
     603             :       /* And the string tables.  */
     604           9 :       dwelf_strtab_free (ctx->section_strtab);
     605           9 :       dwelf_strtab_free (ctx->symbol_strtab);
     606             :     }
     607             : 
     608             :   /* Initialize the lock.  */
     609             :   rwlock_fini (ctx->lock);
     610             : 
     611             :   /* Finally free the data structure.   */
     612           9 :   free (ctx);
     613           9 : }

Generated by: LCOV version 1.13