Coverage Report

Created: 2026-04-13 06:31

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