Coverage Report

Created: 2025-07-12 06:26

/src/libbpf/elfutils/libelf/elf_getshdrstrndx.c
Line
Count
Source (jump to first uncovered line)
1
/* Return section index of section header string table.
2
   Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
3
   This file is part of elfutils.
4
   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
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 <errno.h>
36
#include <gelf.h>
37
#include <stddef.h>
38
39
#include "libelfP.h"
40
#include "common.h"
41
42
43
int
44
elf_getshdrstrndx (Elf *elf, size_t *dst)
45
9.61k
{
46
9.61k
  int result = 0;
47
48
9.61k
  if (elf == NULL)
49
0
    return -1;
50
51
9.61k
  if (unlikely (elf->kind != ELF_K_ELF))
52
0
    {
53
0
      __libelf_seterrno (ELF_E_INVALID_HANDLE);
54
0
      return -1;
55
0
    }
56
57
9.61k
  rwlock_rdlock (elf->lock);
58
59
  /* We rely here on the fact that the `elf' element is a common prefix
60
     of `elf32' and `elf64'.  */
61
9.61k
  assert (offsetof (struct Elf, state.elf.ehdr)
62
9.61k
    == offsetof (struct Elf, state.elf32.ehdr));
63
9.61k
  assert (sizeof (elf->state.elf.ehdr)
64
9.61k
    == sizeof (elf->state.elf32.ehdr));
65
9.61k
  assert (offsetof (struct Elf, state.elf.ehdr)
66
9.61k
    == offsetof (struct Elf, state.elf64.ehdr));
67
9.61k
  assert (sizeof (elf->state.elf.ehdr)
68
9.61k
    == sizeof (elf->state.elf64.ehdr));
69
70
9.61k
  if (unlikely (elf->state.elf.ehdr == NULL))
71
0
    {
72
0
      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
73
0
      result = -1;
74
0
    }
75
9.61k
  else
76
9.61k
    {
77
9.61k
      Elf32_Word num;
78
79
9.61k
      num = (elf->class == ELFCLASS32
80
9.61k
       ? elf->state.elf32.ehdr->e_shstrndx
81
9.61k
       : elf->state.elf64.ehdr->e_shstrndx);
82
83
      /* Determine whether the index is too big to fit in the ELF
84
   header.  */
85
9.61k
      if (unlikely (num == SHN_XINDEX))
86
89
  {
87
    /* Yes.  Search the zeroth section header.  */
88
89
    if (elf->class == ELFCLASS32)
89
0
      {
90
0
        size_t offset;
91
0
        if (unlikely (elf->state.elf32.scns.cnt == 0))
92
0
    {
93
      /* Cannot use SHN_XINDEX without section headers.  */
94
0
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
95
0
      result = -1;
96
0
      goto out;
97
0
    }
98
99
0
        if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
100
0
    {
101
0
      num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
102
0
      goto success;
103
0
    }
104
105
0
        offset = elf->state.elf32.ehdr->e_shoff;
106
107
0
        if (elf->map_address != NULL
108
0
      && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
109
0
      && (ALLOW_UNALIGNED
110
0
          || (((size_t) ((char *) elf->map_address
111
0
         + elf->start_offset + offset))
112
0
        & (__alignof__ (Elf32_Shdr) - 1)) == 0))
113
0
    {
114
      /* First see whether the information in the ELF header is
115
         valid and it does not ask for too much.  */
116
0
      if (unlikely (elf->maximum_size - offset
117
0
        < sizeof (Elf32_Shdr)))
118
0
        {
119
          /* Something is wrong.  */
120
0
          __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
121
0
          result = -1;
122
0
          goto out;
123
0
        }
124
125
      /* We can directly access the memory.  */
126
0
      num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
127
0
           + offset))->sh_link;
128
0
    }
129
0
        else
130
0
    {
131
      /* We avoid reading in all the section headers.  Just read
132
         the first one.  */
133
0
      Elf32_Shdr shdr_mem;
134
0
      ssize_t r;
135
136
0
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
137
0
              sizeof (Elf32_Shdr), offset))
138
0
        != sizeof (Elf32_Shdr)))
139
0
        {
140
          /* We must be able to read this ELF section header.  */
141
0
          if (r < 0)
142
0
      __libelf_seterrno (ELF_E_INVALID_FILE);
143
0
          else
144
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
145
0
          result = -1;
146
0
          goto out;
147
0
        }
148
149
0
      if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
150
0
        CONVERT (shdr_mem.sh_link);
151
0
      num = shdr_mem.sh_link;
152
0
    }
153
0
      }
154
89
    else
155
89
      {
156
89
        if (unlikely (elf->state.elf64.scns.cnt == 0))
157
28
    {
158
      /* Cannot use SHN_XINDEX without section headers.  */
159
28
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
160
28
      result = -1;
161
28
      goto out;
162
28
    }
163
164
61
        if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
165
57
    {
166
57
      num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
167
57
      goto success;
168
57
    }
169
170
4
        size_t offset = elf->state.elf64.ehdr->e_shoff;
171
172
4
        if (elf->map_address != NULL
173
4
      && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
174
4
      && (ALLOW_UNALIGNED
175
0
          || (((size_t) ((char *) elf->map_address
176
0
         + elf->start_offset + offset))
177
0
        & (__alignof__ (Elf64_Shdr) - 1)) == 0))
178
0
    {
179
      /* First see whether the information in the ELF header is
180
         valid and it does not ask for too much.  */
181
0
      if (unlikely (elf->maximum_size - offset
182
0
        < sizeof (Elf64_Shdr)))
183
0
        {
184
          /* Something is wrong.  */
185
0
          __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
186
0
          result = -1;
187
0
          goto out;
188
0
        }
189
190
      /* We can directly access the memory.  */
191
0
      num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
192
0
           + offset))->sh_link;
193
0
    }
194
4
        else
195
4
    {
196
      /* We avoid reading in all the section headers.  Just read
197
         the first one.  */
198
4
      Elf64_Shdr shdr_mem;
199
4
      ssize_t r;
200
201
4
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
202
4
              sizeof (Elf64_Shdr), offset))
203
4
        != sizeof (Elf64_Shdr)))
204
4
        {
205
          /* We must be able to read this ELF section header.  */
206
4
          if (r < 0)
207
4
      __libelf_seterrno (ELF_E_INVALID_FILE);
208
0
          else
209
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
210
4
          result = -1;
211
4
          goto out;
212
4
        }
213
214
0
      if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
215
0
        CONVERT (shdr_mem.sh_link);
216
0
      num = shdr_mem.sh_link;
217
0
    }
218
4
      }
219
89
  }
220
221
      /* Store the result.  */
222
9.57k
    success:
223
9.57k
      *dst = num;
224
9.57k
    }
225
226
9.61k
 out:
227
9.61k
  rwlock_unlock (elf->lock);
228
229
9.61k
  return result;
230
9.61k
}
231
INTDEF(elf_getshdrstrndx)
232
/* Alias for the deprecated name.  */
233
strong_alias (elf_getshdrstrndx, elf_getshstrndx)