Coverage Report

Created: 2025-08-29 06:43

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