1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Free resources associated with Elf descriptor.
21ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard   Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stddef.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/mman.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libelfP.h"
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
431ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardelf_end (Elf *elf)
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *parent;
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf == NULL)
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* This is allowed and is a no-op.  */
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 0;
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure we are alone.  */
52b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath  rwlock_wrlock (elf->lock);
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf->ref_count != 0 && --elf->ref_count != 0)
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Not yet the last activation.  */
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      int result = elf->ref_count;
58b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      rwlock_unlock (elf->lock);
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return result;
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf->kind == ELF_K_AR)
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot remove the descriptor now since we still have some
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 descriptors which depend on it.  But we can free the archive
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 symbol table since this is only available via the archive ELF
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 descriptor.  The long name table cannot be freed yet since
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 the archive headers for the ELF files in the archive point
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 into this array.  */
7059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
7159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	free (elf->state.ar.ar_sym);
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.ar.ar_sym = NULL;
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->state.ar.children != NULL)
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return 0;
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Remove this structure from the children list.  */
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  parent = elf->parent;
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (parent != NULL)
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is tricky.  Lock must be acquire from the father to
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 the child but here we already have the child lock.  We
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 solve this problem by giving free the child lock.  The
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 state of REF_COUNT==0 is handled all over the library, so
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 this should be ok.  */
87b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      rwlock_unlock (elf->lock);
88b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      rwlock_rdlock (parent->lock);
89b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      rwlock_wrlock (elf->lock);
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (parent->state.ar.children == elf)
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	parent->state.ar.children = elf->next;
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  struct Elf *child = parent->state.ar.children;
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (child->next != elf)
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    child = child->next;
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  child->next = elf->next;
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
103b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      rwlock_unlock (parent->lock);
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This was the last activation.  Free all resources.  */
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (elf->kind)
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->state.ar.long_names != NULL)
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (elf->state.ar.long_names);
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
11659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	Elf_Data_Chunk *rawchunks
11759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  = (elf->class == ELFCLASS32
11859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     || (offsetof (struct Elf, state.elf32.rawchunks)
11959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		 == offsetof (struct Elf, state.elf64.rawchunks))
12059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     ? elf->state.elf32.rawchunks
12159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     : elf->state.elf64.rawchunks);
12259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	while (rawchunks != NULL)
12359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  {
12459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    Elf_Data_Chunk *next = rawchunks->next;
12559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
12659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      free (rawchunks->data.d.d_buf);
12759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    free (rawchunks);
12859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    rawchunks = next;
12959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  }
13059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_ScnList *list = (elf->class == ELFCLASS32
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     || (offsetof (struct Elf, state.elf32.scns)
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				 == offsetof (struct Elf, state.elf64.scns))
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     ? &elf->state.elf32.scns
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     : &elf->state.elf64.scns);
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	do
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Free all separately allocated section headers.  */
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    size_t cnt = list->max;
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    while (cnt-- > 0)
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* These pointers can be NULL; it's safe to use
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   'free' since it will check for this.  */
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Scn *scn = &list->data[cnt];
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Data_List *runp;
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* It doesn't matter which pointer.  */
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  free (scn->shdr.e32);
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
153272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		/* Free zdata if uncompressed, but not yet used as
154272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		   rawdata_base.  If it is already used it will be
155272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		   freed below.  */
156272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		if (scn->zdata_base != scn->rawdata_base)
157272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		  free (scn->zdata_base);
158272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* If the file has the same byte order and the
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   architecture doesn't require overly stringent
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   alignment the raw data buffer is the same as the
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   one used for presenting to the caller.  */
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (scn->data_base != scn->rawdata_base)
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  free (scn->data_base);
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* The section data is allocated if we couldn't mmap
167272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		   the file.  Or if we had to decompress.  */
168272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		if (elf->map_address == NULL
169272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard		    || scn->rawdata_base == scn->zdata_base)
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  free (scn->rawdata_base);
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Free the list of data buffers for the section.
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   We don't free the buffers themselves since this
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   is the users job.  */
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		runp = scn->data_list.next;
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		while (runp != NULL)
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf_Data_List *oldp = runp;
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    runp = runp->next;
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((oldp->flags & ELF_F_MALLOCED) != 0)
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      free (oldp);
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Free the memory for the array.  */
186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Elf_ScnList *oldp = list;
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    list = list->next;
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    assert (list == NULL || oldp->cnt == oldp->max);
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (oldp != (elf->class == ELFCLASS32
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 || (offsetof (struct Elf, state.elf32.scns)
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     == offsetof (struct Elf, state.elf64.scns))
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ? &elf->state.elf32.scns
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 : &elf->state.elf64.scns))
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      free (oldp);
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (list != NULL);
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Free the section header.  */
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->state.elf.shdr_malloced  != 0)
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (elf->class == ELFCLASS32
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (offsetof (struct Elf, state.elf32.shdr)
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  == offsetof (struct Elf, state.elf64.shdr))
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ? (void *) elf->state.elf32.shdr
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      : (void *) elf->state.elf64.shdr);
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Free the program header.  */
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (elf->class == ELFCLASS32
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (offsetof (struct Elf, state.elf32.phdr)
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  == offsetof (struct Elf, state.elf64.phdr))
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ? (void *) elf->state.elf32.phdr
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      : (void *) elf->state.elf64.phdr);
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf->map_address != NULL && parent == NULL)
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The file was read or mapped for this descriptor.  */
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((elf->flags & ELF_F_MALLOCED) != 0)
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (elf->map_address);
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if ((elf->flags & ELF_F_MMAPPED) != 0)
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	munmap (elf->map_address, elf->maximum_size);
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
229495501611820a9d5c462fda56045c146f7b922d7Mark Wielaard  rwlock_unlock (elf->lock);
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  rwlock_fini (elf->lock);
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally the descriptor itself.  */
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (elf);
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return (parent != NULL && parent->ref_count == 0
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ? INTUSE(elf_end) (parent) : 0);
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperINTDEF(elf_end)
239