Coverage Report

Created: 2026-02-26 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/elfutils/libelf/elf_end.c
Line
Count
Source
1
/* Free resources associated with Elf descriptor.
2
   Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc.
3
   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
4
   This file is part of elfutils.
5
   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6
7
   This file is free software; you can redistribute it and/or modify
8
   it under the terms of either
9
10
     * the GNU Lesser General Public License as published by the Free
11
       Software Foundation; either version 3 of the License, or (at
12
       your option) any later version
13
14
   or
15
16
     * the GNU General Public License as published by the Free
17
       Software Foundation; either version 2 of the License, or (at
18
       your option) any later version
19
20
   or both in parallel, as here.
21
22
   elfutils is distributed in the hope that it will be useful, but
23
   WITHOUT ANY WARRANTY; without even the implied warranty of
24
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
   General Public License for more details.
26
27
   You should have received copies of the GNU General Public License and
28
   the GNU Lesser General Public License along with this program.  If
29
   not, see <http://www.gnu.org/licenses/>.  */
30
31
#ifdef HAVE_CONFIG_H
32
# include <config.h>
33
#endif
34
35
#include <assert.h>
36
#include <search.h>
37
#include <stddef.h>
38
#include <stdlib.h>
39
40
#include "libelfP.h"
41
42
43
static void
44
free_chunk (void *n)
45
3.15k
{
46
3.15k
  Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n;
47
3.15k
  if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED)
48
2.51k
    free (rawchunk->data.d.d_buf);
49
3.15k
  free (rawchunk);
50
3.15k
}
51
52
int
53
elf_end (Elf *elf)
54
247k
{
55
247k
  Elf *parent;
56
57
247k
  if (elf == NULL)
58
    /* This is allowed and is a no-op.  */
59
112
    return 0;
60
61
  /* Make sure we are alone.  */
62
247k
  rwlock_wrlock (elf->lock);
63
64
247k
  if (elf->ref_count != 0 && --elf->ref_count != 0)
65
0
    {
66
      /* Not yet the last activation.  */
67
0
      int result = elf->ref_count;
68
0
      rwlock_unlock (elf->lock);
69
0
      return result;
70
0
    }
71
72
247k
  if (elf->kind == ELF_K_AR)
73
220k
    {
74
      /* We cannot remove the descriptor now since we still have some
75
   descriptors which depend on it.  But we can free the archive
76
   symbol table since this is only available via the archive ELF
77
   descriptor.  The long name table cannot be freed yet since
78
   the archive headers for the ELF files in the archive point
79
   into this array.  */
80
220k
      if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
81
220k
  free (elf->state.ar.ar_sym);
82
220k
      elf->state.ar.ar_sym = NULL;
83
84
220k
      if (elf->state.ar.children != NULL)
85
23.1k
  {
86
23.1k
    rwlock_unlock(elf->lock);
87
23.1k
    return 0;
88
23.1k
  }
89
220k
    }
90
91
  /* Remove this structure from the children list.  */
92
224k
  parent = elf->parent;
93
224k
  if (parent != NULL)
94
210k
    {
95
      /* This is tricky.  Lock must be acquire from the father to
96
   the child but here we already have the child lock.  We
97
   solve this problem by giving free the child lock.  The
98
   state of REF_COUNT==0 is handled all over the library, so
99
   this should be ok.  */
100
210k
      rwlock_unlock (elf->lock);
101
210k
      rwlock_rdlock (parent->lock);
102
210k
      rwlock_wrlock (elf->lock);
103
104
210k
      if (parent->state.ar.children == elf)
105
198k
  parent->state.ar.children = elf->next;
106
12.2k
      else
107
12.2k
  {
108
12.2k
    struct Elf *child = parent->state.ar.children;
109
110
463k
    while (child->next != elf)
111
451k
      child = child->next;
112
113
12.2k
    child->next = elf->next;
114
12.2k
  }
115
116
210k
      rwlock_unlock (parent->lock);
117
210k
    }
118
119
224k
  if (elf->elf_ar_hdr.ar_name != NULL)
120
210k
    free (elf->elf_ar_hdr.ar_name);
121
122
224k
  if (elf->elf_ar_hdr.ar_rawname != NULL)
123
210k
    free (elf->elf_ar_hdr.ar_rawname);
124
125
  /* This was the last activation.  Free all resources.  */
126
224k
  switch (elf->kind)
127
224k
    {
128
197k
    case ELF_K_AR:
129
197k
      if (elf->state.ar.long_names != NULL)
130
212
  free (elf->state.ar.long_names);
131
197k
      break;
132
133
20.4k
    case ELF_K_ELF:
134
20.4k
      {
135
20.4k
  search_tree *rawchunk_tree
136
20.4k
    = (elf->class == ELFCLASS32
137
7.30k
       || (offsetof (struct Elf, state.elf32.rawchunk_tree)
138
7.30k
     == offsetof (struct Elf, state.elf64.rawchunk_tree))
139
20.4k
       ? &elf->state.elf32.rawchunk_tree
140
20.4k
       : &elf->state.elf64.rawchunk_tree);
141
142
20.4k
  eu_search_tree_fini (rawchunk_tree, free_chunk);
143
144
20.4k
  Elf_ScnList *list = (elf->class == ELFCLASS32
145
7.30k
           || (offsetof (struct Elf, state.elf32.scns)
146
7.30k
         == offsetof (struct Elf, state.elf64.scns))
147
20.4k
           ? &elf->state.elf32.scns
148
20.4k
           : &elf->state.elf64.scns);
149
150
20.4k
  do
151
20.4k
    {
152
      /* Free all separately allocated section headers.  */
153
20.4k
      size_t cnt = list->max;
154
155
3.38M
      while (cnt-- > 0)
156
3.36M
        {
157
    /* These pointers can be NULL; it's safe to use
158
       'free' since it will check for this.  */
159
3.36M
    Elf_Scn *scn = &list->data[cnt];
160
3.36M
    Elf_Data_List *runp;
161
162
3.36M
    if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
163
      /* It doesn't matter which pointer.  */
164
0
      free (scn->shdr.e32);
165
166
    /* Free zdata if uncompressed, but not yet used as
167
       rawdata_base.  If it is already used it will be
168
       freed below.  */
169
3.36M
    if (scn->zdata_base != scn->rawdata_base)
170
642k
      {
171
642k
        free (scn->zdata_base);
172
642k
        scn->zdata_base = NULL;
173
642k
      }
174
175
    /* If the file has the same byte order and the
176
       architecture doesn't require overly stringent
177
       alignment the raw data buffer is the same as the
178
       one used for presenting to the caller.  */
179
3.36M
    if (scn->data_base != scn->rawdata_base)
180
5.50k
      free (scn->data_base);
181
182
    /* The section data is allocated if we couldn't mmap
183
       the file.  Or if we had to decompress.  */
184
3.36M
    if (elf->map_address == NULL
185
3.36M
        || scn->rawdata_base == scn->zdata_base
186
642k
        || (scn->flags & ELF_F_MALLOCED) != 0)
187
2.72M
      free (scn->rawdata_base);
188
189
    /* Free the list of data buffers for the section.
190
       We don't free the buffers themselves since this
191
       is the users job.  */
192
3.36M
    runp = scn->data_list.next;
193
3.36M
    while (runp != NULL)
194
0
      {
195
0
        Elf_Data_List *oldp = runp;
196
0
        runp = runp->next;
197
0
        if ((oldp->flags & ELF_F_MALLOCED) != 0)
198
0
          free (oldp);
199
0
      }
200
3.36M
        }
201
202
      /* Free the memory for the array.  */
203
20.4k
      Elf_ScnList *oldp = list;
204
20.4k
      list = list->next;
205
20.4k
      assert (list == NULL || oldp->cnt == oldp->max);
206
20.4k
      if (oldp != (elf->class == ELFCLASS32
207
7.30k
       || (offsetof (struct Elf, state.elf32.scns)
208
7.30k
           == offsetof (struct Elf, state.elf64.scns))
209
20.4k
       ? &elf->state.elf32.scns
210
20.4k
       : &elf->state.elf64.scns))
211
0
        free (oldp);
212
20.4k
    }
213
20.4k
  while (list != NULL);
214
20.4k
      }
215
216
      /* Free the section header.  */
217
20.4k
      if (elf->state.elf.shdr_malloced  != 0)
218
2.25k
  free (elf->class == ELFCLASS32
219
1.14k
        || (offsetof (struct Elf, state.elf32.shdr)
220
1.14k
      == offsetof (struct Elf, state.elf64.shdr))
221
2.25k
        ? (void *) elf->state.elf32.shdr
222
2.25k
        : (void *) elf->state.elf64.shdr);
223
224
      /* Free the program header.  */
225
20.4k
      if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
226
1.31k
  free (elf->class == ELFCLASS32
227
554
        || (offsetof (struct Elf, state.elf32.phdr)
228
554
      == offsetof (struct Elf, state.elf64.phdr))
229
1.31k
        ? (void *) elf->state.elf32.phdr
230
1.31k
        : (void *) elf->state.elf64.phdr);
231
20.4k
      break;
232
233
6.44k
    default:
234
6.44k
      break;
235
224k
    }
236
237
224k
  if (elf->map_address != NULL && parent == NULL)
238
13.9k
    {
239
      /* The file was read or mapped for this descriptor.  */
240
13.9k
      if ((elf->flags & ELF_F_MALLOCED) != 0)
241
2.96k
  free (elf->map_address);
242
10.9k
      else if ((elf->flags & ELF_F_MMAPPED) != 0)
243
10.7k
  munmap (elf->map_address, elf->maximum_size);
244
13.9k
    }
245
246
224k
  rwlock_unlock (elf->lock);
247
224k
  rwlock_fini (elf->lock);
248
249
  /* Finally the descriptor itself.  */
250
224k
  free (elf);
251
252
224k
  return (parent != NULL && parent->ref_count == 0
253
224k
    ? INTUSE(elf_end) (parent) : 0);
254
224k
}
255
INTDEF(elf_end)