LCOV - code coverage report
Current view: top level - libelf - elf_end.c (source / functions) Hit Total Coverage
Test: elfutils-0.174 Lines: 65 67 97.0 %
Date: 2018-09-14 13:30:33 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Free resources associated with Elf descriptor.
       2             :    Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
       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 <stddef.h>
      36             : #include <stdlib.h>
      37             : #include <sys/mman.h>
      38             : 
      39             : #include "libelfP.h"
      40             : 
      41             : 
      42             : int
      43       14998 : elf_end (Elf *elf)
      44             : {
      45             :   Elf *parent;
      46             : 
      47       14998 :   if (elf == NULL)
      48             :     /* This is allowed and is a no-op.  */
      49             :     return 0;
      50             : 
      51             :   /* Make sure we are alone.  */
      52             :   rwlock_wrlock (elf->lock);
      53             : 
      54       14723 :   if (elf->ref_count != 0 && --elf->ref_count != 0)
      55             :     {
      56             :       /* Not yet the last activation.  */
      57             :       int result = elf->ref_count;
      58             :       rwlock_unlock (elf->lock);
      59             :       return result;
      60             :     }
      61             : 
      62       14723 :   if (elf->kind == ELF_K_AR)
      63             :     {
      64             :       /* We cannot remove the descriptor now since we still have some
      65             :          descriptors which depend on it.  But we can free the archive
      66             :          symbol table since this is only available via the archive ELF
      67             :          descriptor.  The long name table cannot be freed yet since
      68             :          the archive headers for the ELF files in the archive point
      69             :          into this array.  */
      70         127 :       if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
      71         127 :         free (elf->state.ar.ar_sym);
      72         127 :       elf->state.ar.ar_sym = NULL;
      73             : 
      74         127 :       if (elf->state.ar.children != NULL)
      75             :         return 0;
      76             :     }
      77             : 
      78             :   /* Remove this structure from the children list.  */
      79       14723 :   parent = elf->parent;
      80       14723 :   if (parent != NULL)
      81             :     {
      82             :       /* This is tricky.  Lock must be acquire from the father to
      83             :          the child but here we already have the child lock.  We
      84             :          solve this problem by giving free the child lock.  The
      85             :          state of REF_COUNT==0 is handled all over the library, so
      86             :          this should be ok.  */
      87             :       rwlock_unlock (elf->lock);
      88             :       rwlock_rdlock (parent->lock);
      89             :       rwlock_wrlock (elf->lock);
      90             : 
      91        7232 :       if (parent->state.ar.children == elf)
      92        7232 :         parent->state.ar.children = elf->next;
      93             :       else
      94             :         {
      95             :           struct Elf *child = parent->state.ar.children;
      96             : 
      97           0 :           while (child->next != elf)
      98             :             child = child->next;
      99             : 
     100           0 :           child->next = elf->next;
     101             :         }
     102             : 
     103             :       rwlock_unlock (parent->lock);
     104             :     }
     105             : 
     106             :   /* This was the last activation.  Free all resources.  */
     107       14723 :   switch (elf->kind)
     108             :     {
     109         127 :     case ELF_K_AR:
     110         127 :       if (elf->state.ar.long_names != NULL)
     111         102 :         free (elf->state.ar.long_names);
     112             :       break;
     113             : 
     114       14351 :     case ELF_K_ELF:
     115       14351 :       {
     116       14351 :         Elf_Data_Chunk *rawchunks
     117             :           = (elf->class == ELFCLASS32
     118             :              || (offsetof (struct Elf, state.elf32.rawchunks)
     119             :                  == offsetof (struct Elf, state.elf64.rawchunks))
     120             :              ? elf->state.elf32.rawchunks
     121             :              : elf->state.elf64.rawchunks);
     122       29556 :         while (rawchunks != NULL)
     123             :           {
     124         854 :             Elf_Data_Chunk *next = rawchunks->next;
     125         854 :             if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
     126         336 :               free (rawchunks->data.d.d_buf);
     127         854 :             free (rawchunks);
     128         854 :             rawchunks = next;
     129             :           }
     130             : 
     131       14351 :         Elf_ScnList *list = (elf->class == ELFCLASS32
     132             :                              || (offsetof (struct Elf, state.elf32.scns)
     133             :                                  == offsetof (struct Elf, state.elf64.scns))
     134             :                              ? &elf->state.elf32.scns
     135             :                              : &elf->state.elf64.scns);
     136             : 
     137             :         do
     138             :           {
     139             :             /* Free all separately allocated section headers.  */
     140       15225 :             size_t cnt = list->max;
     141             : 
     142    10776958 :             while (cnt-- > 0)
     143             :               {
     144             :                 /* These pointers can be NULL; it's safe to use
     145             :                    'free' since it will check for this.  */
     146    10746508 :                 Elf_Scn *scn = &list->data[cnt];
     147             :                 Elf_Data_List *runp;
     148             : 
     149    10746508 :                 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
     150             :                   /* It doesn't matter which pointer.  */
     151     2697354 :                   free (scn->shdr.e32);
     152             : 
     153             :                 /* Free zdata if uncompressed, but not yet used as
     154             :                    rawdata_base.  If it is already used it will be
     155             :                    freed below.  */
     156    10746508 :                 if (scn->zdata_base != scn->rawdata_base)
     157     2803726 :                   free (scn->zdata_base);
     158             : 
     159             :                 /* If the file has the same byte order and the
     160             :                    architecture doesn't require overly stringent
     161             :                    alignment the raw data buffer is the same as the
     162             :                    one used for presenting to the caller.  */
     163    10746508 :                 if (scn->data_base != scn->rawdata_base)
     164     1054598 :                   free (scn->data_base);
     165             : 
     166             :                 /* The section data is allocated if we couldn't mmap
     167             :                    the file.  Or if we had to decompress.  */
     168    10746508 :                 if (elf->map_address == NULL
     169     6733058 :                     || scn->rawdata_base == scn->zdata_base
     170     1551450 :                     || (scn->flags & ELF_F_MALLOCED) != 0)
     171     9195063 :                   free (scn->rawdata_base);
     172             : 
     173             :                 /* Free the list of data buffers for the section.
     174             :                    We don't free the buffers themselves since this
     175             :                    is the users job.  */
     176    10746508 :                 runp = scn->data_list.next;
     177    21493110 :                 while (runp != NULL)
     178             :                   {
     179          94 :                     Elf_Data_List *oldp = runp;
     180          94 :                     runp = runp->next;
     181          94 :                     if ((oldp->flags & ELF_F_MALLOCED) != 0)
     182          94 :                       free (oldp);
     183             :                   }
     184             :               }
     185             : 
     186             :             /* Free the memory for the array.  */
     187       15225 :             Elf_ScnList *oldp = list;
     188       15225 :             list = list->next;
     189       15225 :             assert (list == NULL || oldp->cnt == oldp->max);
     190       15225 :             if (oldp != (elf->class == ELFCLASS32
     191             :                          || (offsetof (struct Elf, state.elf32.scns)
     192             :                              == offsetof (struct Elf, state.elf64.scns))
     193             :                          ? &elf->state.elf32.scns
     194             :                          : &elf->state.elf64.scns))
     195         874 :               free (oldp);
     196             :           }
     197       15225 :         while (list != NULL);
     198             :       }
     199             : 
     200             :       /* Free the section header.  */
     201       14351 :       if (elf->state.elf.shdr_malloced  != 0)
     202        1361 :         free (elf->class == ELFCLASS32
     203             :               || (offsetof (struct Elf, state.elf32.shdr)
     204             :                   == offsetof (struct Elf, state.elf64.shdr))
     205        1361 :               ? (void *) elf->state.elf32.shdr
     206             :               : (void *) elf->state.elf64.shdr);
     207             : 
     208             :       /* Free the program header.  */
     209       14351 :       if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
     210         727 :         free (elf->class == ELFCLASS32
     211             :               || (offsetof (struct Elf, state.elf32.phdr)
     212             :                   == offsetof (struct Elf, state.elf64.phdr))
     213         727 :               ? (void *) elf->state.elf32.phdr
     214             :               : (void *) elf->state.elf64.phdr);
     215             :       break;
     216             : 
     217             :     default:
     218             :       break;
     219             :     }
     220             : 
     221       14723 :   if (elf->map_address != NULL && parent == NULL)
     222             :     {
     223             :       /* The file was read or mapped for this descriptor.  */
     224        6690 :       if ((elf->flags & ELF_F_MALLOCED) != 0)
     225          20 :         free (elf->map_address);
     226        6670 :       else if ((elf->flags & ELF_F_MMAPPED) != 0)
     227        6634 :         munmap (elf->map_address, elf->maximum_size);
     228             :     }
     229             : 
     230             :   rwlock_unlock (elf->lock);
     231             :   rwlock_fini (elf->lock);
     232             : 
     233             :   /* Finally the descriptor itself.  */
     234       14723 :   free (elf);
     235             : 
     236        7232 :   return (parent != NULL && parent->ref_count == 0
     237       14723 :           ? INTUSE(elf_end) (parent) : 0);
     238             : }
     239             : INTDEF(elf_end)

Generated by: LCOV version 1.13