Coverage Report

Created: 2026-07-22 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libbpf/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
   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
10.7k
{
44
10.7k
  Elf *parent;
45
46
10.7k
  if (elf == NULL)
47
    /* This is allowed and is a no-op.  */
48
0
    return 0;
49
50
  /* Make sure we are alone.  */
51
10.7k
  rwlock_wrlock (elf->lock);
52
53
10.7k
  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
10.7k
  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
10.7k
  parent = elf->parent;
79
10.7k
  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
10.7k
  switch (elf->kind)
107
10.7k
    {
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
10.6k
    case ELF_K_ELF:
114
10.6k
      {
115
10.6k
  Elf_Data_Chunk *rawchunks
116
10.6k
    = (elf->class == ELFCLASS32
117
10.1k
       || (offsetof (struct Elf, state.elf32.rawchunks)
118
10.1k
     == offsetof (struct Elf, state.elf64.rawchunks))
119
10.6k
       ? elf->state.elf32.rawchunks
120
10.6k
       : elf->state.elf64.rawchunks);
121
10.6k
  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
10.6k
  Elf_ScnList *list = (elf->class == ELFCLASS32
131
10.1k
           || (offsetof (struct Elf, state.elf32.scns)
132
10.1k
         == offsetof (struct Elf, state.elf64.scns))
133
10.6k
           ? &elf->state.elf32.scns
134
10.6k
           : &elf->state.elf64.scns);
135
136
10.6k
  do
137
10.6k
    {
138
      /* Free all separately allocated section headers.  */
139
10.6k
      size_t cnt = list->max;
140
141
515k
      while (cnt-- > 0)
142
505k
        {
143
    /* These pointers can be NULL; it's safe to use
144
       'free' since it will check for this.  */
145
505k
    Elf_Scn *scn = &list->data[cnt];
146
505k
    Elf_Data_List *runp;
147
148
505k
    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
505k
    if (scn->zdata_base != scn->rawdata_base)
156
211k
      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
505k
    if (scn->data_base != scn->rawdata_base)
163
18.6k
      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
505k
    if (elf->map_address == NULL
168
505k
        || scn->rawdata_base == scn->zdata_base
169
211k
        || (scn->flags & ELF_F_MALLOCED) != 0)
170
293k
      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
505k
    runp = scn->data_list.next;
176
505k
    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
505k
        }
184
185
      /* Free the memory for the array.  */
186
10.6k
      Elf_ScnList *oldp = list;
187
10.6k
      list = list->next;
188
10.6k
      assert (list == NULL || oldp->cnt == oldp->max);
189
10.6k
      if (oldp != (elf->class == ELFCLASS32
190
10.1k
       || (offsetof (struct Elf, state.elf32.scns)
191
10.1k
           == offsetof (struct Elf, state.elf64.scns))
192
10.6k
       ? &elf->state.elf32.scns
193
10.6k
       : &elf->state.elf64.scns))
194
0
        free (oldp);
195
10.6k
    }
196
10.6k
  while (list != NULL);
197
10.6k
      }
198
199
      /* Free the section header.  */
200
10.6k
      if (elf->state.elf.shdr_malloced  != 0)
201
2.03k
  free (elf->class == ELFCLASS32
202
2.03k
        || (offsetof (struct Elf, state.elf32.shdr)
203
2.03k
      == offsetof (struct Elf, state.elf64.shdr))
204
2.03k
        ? (void *) elf->state.elf32.shdr
205
2.03k
        : (void *) elf->state.elf64.shdr);
206
207
      /* Free the program header.  */
208
10.6k
      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
10.6k
      break;
215
216
111
    default:
217
111
      break;
218
10.7k
    }
219
220
10.7k
  if (elf->map_address != NULL && parent == NULL)
221
10.7k
    {
222
      /* The file was read or mapped for this descriptor.  */
223
10.7k
      if ((elf->flags & ELF_F_MALLOCED) != 0)
224
0
  free (elf->map_address);
225
10.7k
      else if ((elf->flags & ELF_F_MMAPPED) != 0)
226
0
  munmap (elf->map_address, elf->maximum_size);
227
10.7k
    }
228
229
10.7k
  rwlock_unlock (elf->lock);
230
10.7k
  rwlock_fini (elf->lock);
231
232
  /* Finally the descriptor itself.  */
233
10.7k
  free (elf);
234
235
10.7k
  return (parent != NULL && parent->ref_count == 0
236
10.7k
    ? INTUSE(elf_end) (parent) : 0);
237
10.7k
}
238
INTDEF(elf_end)