LCOV - code coverage report
Current view: top level - libelf - elf_end.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 62 64 96.9 %
Date: 2017-05-05 10:17:09 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       14253 : elf_end (Elf *elf)
      44             : {
      45             :   Elf *parent;
      46             : 
      47       14253 :   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       13985 :   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       13985 :   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         124 :       if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
      71         124 :         free (elf->state.ar.ar_sym);
      72         124 :       elf->state.ar.ar_sym = NULL;
      73             : 
      74         124 :       if (elf->state.ar.children != NULL)
      75             :         return 0;
      76             :     }
      77             : 
      78             :   /* Remove this structure from the children list.  */
      79       13985 :   parent = elf->parent;
      80       13985 :   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        7193 :       if (parent->state.ar.children == elf)
      92        7193 :         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       13985 :   switch (elf->kind)
     108             :     {
     109             :     case ELF_K_AR:
     110         124 :       if (elf->state.ar.long_names != NULL)
     111         102 :         free (elf->state.ar.long_names);
     112             :       break;
     113             : 
     114             :     case ELF_K_ELF:
     115             :       {
     116       13618 :         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       27962 :         while (rawchunks != NULL)
     123             :           {
     124         726 :             Elf_Data_Chunk *next = rawchunks->next;
     125         726 :             if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
     126         336 :               free (rawchunks->data.d.d_buf);
     127         726 :             free (rawchunks);
     128         726 :             rawchunks = next;
     129             :           }
     130             : 
     131       13618 :         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       13924 :             size_t cnt = list->max;
     141             : 
     142      933084 :             while (cnt-- > 0)
     143             :               {
     144             :                 /* These pointers can be NULL; it's safe to use
     145             :                    'free' since it will check for this.  */
     146      905236 :                 Elf_Scn *scn = &list->data[cnt];
     147             :                 Elf_Data_List *runp;
     148             : 
     149      905236 :                 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
     150             :                   /* It doesn't matter which pointer.  */
     151      204183 :                   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      905236 :                 if (scn->zdata_base != scn->rawdata_base)
     157      244962 :                   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      905236 :                 if (scn->data_base != scn->rawdata_base)
     164        3855 :                   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      905236 :                 if (elf->map_address == NULL
     169      675472 :                     || scn->rawdata_base == scn->zdata_base
     170      239908 :                     || (scn->flags & ELF_F_MALLOCED) != 0)
     171      665333 :                   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      905236 :                 runp = scn->data_list.next;
     177     1810566 :                 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       13924 :             Elf_ScnList *oldp = list;
     188       13924 :             list = list->next;
     189       13924 :             assert (list == NULL || oldp->cnt == oldp->max);
     190       13924 :             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         306 :               free (oldp);
     196             :           }
     197       13924 :         while (list != NULL);
     198             :       }
     199             : 
     200             :       /* Free the section header.  */
     201       13618 :       if (elf->state.elf.shdr_malloced  != 0)
     202         870 :         free (elf->class == ELFCLASS32
     203             :               || (offsetof (struct Elf, state.elf32.shdr)
     204             :                   == offsetof (struct Elf, state.elf64.shdr))
     205         870 :               ? (void *) elf->state.elf32.shdr
     206             :               : (void *) elf->state.elf64.shdr);
     207             : 
     208             :       /* Free the program header.  */
     209       13618 :       if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
     210         563 :         free (elf->class == ELFCLASS32
     211             :               || (offsetof (struct Elf, state.elf32.phdr)
     212             :                   == offsetof (struct Elf, state.elf64.phdr))
     213         563 :               ? (void *) elf->state.elf32.phdr
     214             :               : (void *) elf->state.elf64.phdr);
     215             :       break;
     216             : 
     217             :     default:
     218             :       break;
     219             :     }
     220             : 
     221       13985 :   if (elf->map_address != NULL && parent == NULL)
     222             :     {
     223             :       /* The file was read or mapped for this descriptor.  */
     224        6133 :       if ((elf->flags & ELF_F_MALLOCED) != 0)
     225          17 :         free (elf->map_address);
     226        6116 :       else if ((elf->flags & ELF_F_MMAPPED) != 0)
     227        6083 :         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       13985 :   free (elf);
     235             : 
     236        7193 :   return (parent != NULL && parent->ref_count == 0
     237       13985 :           ? INTUSE(elf_end) (parent) : 0);
     238             : }
     239             : INTDEF(elf_end)

Generated by: LCOV version 1.12