Coverage Report

Created: 2025-11-10 06:03

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