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

Generated by: LCOV version 1.13