Coverage Report

Created: 2025-07-11 06:46

/src/elfutils/libelf/elf_end.c
Line
Count
Source (jump to first uncovered line)
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
5.65k
{
46
5.65k
  Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n;
47
5.65k
  if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED)
48
4.11k
    free (rawchunk->data.d.d_buf);
49
5.65k
  free (rawchunk);
50
5.65k
}
51
52
int
53
elf_end (Elf *elf)
54
206k
{
55
206k
  Elf *parent;
56
57
206k
  if (elf == NULL)
58
    /* This is allowed and is a no-op.  */
59
102
    return 0;
60
61
  /* Make sure we are alone.  */
62
206k
  rwlock_wrlock (elf->lock);
63
64
206k
  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
206k
  if (elf->kind == ELF_K_AR)
73
180k
    {
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
180k
      if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
81
180k
  free (elf->state.ar.ar_sym);
82
180k
      elf->state.ar.ar_sym = NULL;
83
84
180k
      if (elf->state.ar.children != NULL)
85
17.5k
  {
86
17.5k
    rwlock_unlock(elf->lock);
87
17.5k
    return 0;
88
17.5k
  }
89
180k
    }
90
91
  /* Remove this structure from the children list.  */
92
188k
  parent = elf->parent;
93
188k
  if (parent != NULL)
94
175k
    {
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
175k
      rwlock_unlock (elf->lock);
101
175k
      rwlock_rdlock (parent->lock);
102
175k
      rwlock_wrlock (elf->lock);
103
104
175k
      if (parent->state.ar.children == elf)
105
162k
  parent->state.ar.children = elf->next;
106
12.9k
      else
107
12.9k
  {
108
12.9k
    struct Elf *child = parent->state.ar.children;
109
110
586k
    while (child->next != elf)
111
573k
      child = child->next;
112
113
12.9k
    child->next = elf->next;
114
12.9k
  }
115
116
175k
      rwlock_unlock (parent->lock);
117
175k
    }
118
119
  /* This was the last activation.  Free all resources.  */
120
188k
  switch (elf->kind)
121
188k
    {
122
162k
    case ELF_K_AR:
123
162k
      if (elf->state.ar.long_names != NULL)
124
323
  free (elf->state.ar.long_names);
125
162k
      break;
126
127
20.6k
    case ELF_K_ELF:
128
20.6k
      {
129
20.6k
  search_tree *rawchunk_tree
130
20.6k
    = (elf->class == ELFCLASS32
131
20.6k
       || (offsetof (struct Elf, state.elf32.rawchunk_tree)
132
6.60k
     == offsetof (struct Elf, state.elf64.rawchunk_tree))
133
20.6k
       ? &elf->state.elf32.rawchunk_tree
134
20.6k
       : &elf->state.elf64.rawchunk_tree);
135
136
20.6k
  eu_search_tree_fini (rawchunk_tree, free_chunk);
137
138
20.6k
  Elf_ScnList *list = (elf->class == ELFCLASS32
139
20.6k
           || (offsetof (struct Elf, state.elf32.scns)
140
6.60k
         == offsetof (struct Elf, state.elf64.scns))
141
20.6k
           ? &elf->state.elf32.scns
142
20.6k
           : &elf->state.elf64.scns);
143
144
20.6k
  do
145
20.6k
    {
146
      /* Free all separately allocated section headers.  */
147
20.6k
      size_t cnt = list->max;
148
149
3.30M
      while (cnt-- > 0)
150
3.28M
        {
151
    /* These pointers can be NULL; it's safe to use
152
       'free' since it will check for this.  */
153
3.28M
    Elf_Scn *scn = &list->data[cnt];
154
3.28M
    Elf_Data_List *runp;
155
156
3.28M
    if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
157
      /* It doesn't matter which pointer.  */
158
0
      free (scn->shdr.e32);
159
160
    /* Free zdata if uncompressed, but not yet used as
161
       rawdata_base.  If it is already used it will be
162
       freed below.  */
163
3.28M
    if (scn->zdata_base != scn->rawdata_base)
164
693k
      {
165
693k
        free (scn->zdata_base);
166
693k
        scn->zdata_base = NULL;
167
693k
      }
168
169
    /* If the file has the same byte order and the
170
       architecture doesn't require overly stringent
171
       alignment the raw data buffer is the same as the
172
       one used for presenting to the caller.  */
173
3.28M
    if (scn->data_base != scn->rawdata_base)
174
5.99k
      free (scn->data_base);
175
176
    /* The section data is allocated if we couldn't mmap
177
       the file.  Or if we had to decompress.  */
178
3.28M
    if (elf->map_address == NULL
179
3.28M
        || scn->rawdata_base == scn->zdata_base
180
3.28M
        || (scn->flags & ELF_F_MALLOCED) != 0)
181
2.58M
      free (scn->rawdata_base);
182
183
    /* Free the list of data buffers for the section.
184
       We don't free the buffers themselves since this
185
       is the users job.  */
186
3.28M
    runp = scn->data_list.next;
187
3.28M
    while (runp != NULL)
188
0
      {
189
0
        Elf_Data_List *oldp = runp;
190
0
        runp = runp->next;
191
0
        if ((oldp->flags & ELF_F_MALLOCED) != 0)
192
0
          free (oldp);
193
0
      }
194
3.28M
        }
195
196
      /* Free the memory for the array.  */
197
20.6k
      Elf_ScnList *oldp = list;
198
20.6k
      list = list->next;
199
20.6k
      assert (list == NULL || oldp->cnt == oldp->max);
200
20.6k
      if (oldp != (elf->class == ELFCLASS32
201
20.6k
       || (offsetof (struct Elf, state.elf32.scns)
202
6.60k
           == offsetof (struct Elf, state.elf64.scns))
203
20.6k
       ? &elf->state.elf32.scns
204
20.6k
       : &elf->state.elf64.scns))
205
0
        free (oldp);
206
20.6k
    }
207
20.6k
  while (list != NULL);
208
20.6k
      }
209
210
      /* Free the section header.  */
211
20.6k
      if (elf->state.elf.shdr_malloced  != 0)
212
1.95k
  free (elf->class == ELFCLASS32
213
1.95k
        || (offsetof (struct Elf, state.elf32.shdr)
214
1.00k
      == offsetof (struct Elf, state.elf64.shdr))
215
1.95k
        ? (void *) elf->state.elf32.shdr
216
1.95k
        : (void *) elf->state.elf64.shdr);
217
218
      /* Free the program header.  */
219
20.6k
      if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
220
1.30k
  free (elf->class == ELFCLASS32
221
1.30k
        || (offsetof (struct Elf, state.elf32.phdr)
222
531
      == offsetof (struct Elf, state.elf64.phdr))
223
1.30k
        ? (void *) elf->state.elf32.phdr
224
1.30k
        : (void *) elf->state.elf64.phdr);
225
20.6k
      break;
226
227
5.21k
    default:
228
5.21k
      break;
229
188k
    }
230
231
188k
  if (elf->map_address != NULL && parent == NULL)
232
12.8k
    {
233
      /* The file was read or mapped for this descriptor.  */
234
12.8k
      if ((elf->flags & ELF_F_MALLOCED) != 0)
235
2.56k
  free (elf->map_address);
236
10.2k
      else if ((elf->flags & ELF_F_MMAPPED) != 0)
237
10.1k
  munmap (elf->map_address, elf->maximum_size);
238
12.8k
    }
239
240
188k
  rwlock_unlock (elf->lock);
241
188k
  rwlock_fini (elf->lock);
242
243
  /* Finally the descriptor itself.  */
244
188k
  free (elf);
245
246
188k
  return (parent != NULL && parent->ref_count == 0
247
188k
    ? INTUSE(elf_end) (parent) : 0);
248
188k
}
249
INTDEF(elf_end)