Coverage Report

Created: 2026-04-13 06:32

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
9.93k
{
45
9.93k
  int result = 0;
46
47
9.93k
  if (elf == NULL)
48
0
    return -1;
49
50
9.93k
  if (unlikely (elf->kind != ELF_K_ELF))
51
0
    {
52
0
      __libelf_seterrno (ELF_E_INVALID_HANDLE);
53
0
      return -1;
54
0
    }
55
56
9.93k
  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
9.93k
  eu_static_assert (offsetof (struct Elf, state.elf.ehdr)
61
9.93k
        == offsetof (struct Elf, state.elf32.ehdr));
62
9.93k
  eu_static_assert (sizeof (elf->state.elf.ehdr)
63
9.93k
        == sizeof (elf->state.elf32.ehdr));
64
9.93k
  eu_static_assert (offsetof (struct Elf, state.elf.ehdr)
65
9.93k
        == offsetof (struct Elf, state.elf64.ehdr));
66
9.93k
  eu_static_assert (sizeof (elf->state.elf.ehdr)
67
9.93k
        == sizeof (elf->state.elf64.ehdr));
68
69
9.93k
  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
9.93k
  else
75
9.93k
    {
76
9.93k
      Elf32_Word num;
77
78
9.93k
      num = (elf->class == ELFCLASS32
79
9.93k
       ? elf->state.elf32.ehdr->e_shstrndx
80
9.93k
       : elf->state.elf64.ehdr->e_shstrndx);
81
82
      /* Determine whether the index is too big to fit in the ELF
83
   header.  */
84
9.93k
      if (unlikely (num == SHN_XINDEX))
85
312
  {
86
    /* Yes.  Search the zeroth section header.  */
87
312
    if (elf->class == ELFCLASS32)
88
253
      {
89
253
        size_t offset;
90
253
        if (unlikely (elf->state.elf32.scns.cnt == 0))
91
12
    {
92
      /* Cannot use SHN_XINDEX without section headers.  */
93
12
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
94
12
      result = -1;
95
12
      goto out;
96
12
    }
97
98
241
        if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
99
240
    {
100
240
      num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
101
240
      goto success;
102
240
    }
103
104
1
        offset = elf->state.elf32.ehdr->e_shoff;
105
106
1
        if (elf->map_address != NULL
107
1
      && 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
1
        else
129
1
    {
130
      /* We avoid reading in all the section headers.  Just read
131
         the first one.  */
132
1
      Elf32_Shdr shdr_mem;
133
1
      ssize_t r;
134
135
1
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
136
1
              sizeof (Elf32_Shdr), offset))
137
1
        != sizeof (Elf32_Shdr)))
138
1
        {
139
          /* We must be able to read this ELF section header.  */
140
1
          if (r < 0)
141
1
      __libelf_seterrno (ELF_E_INVALID_FILE);
142
0
          else
143
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
144
1
          result = -1;
145
1
          goto out;
146
1
        }
147
148
0
      if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
149
0
        CONVERT (shdr_mem.sh_link);
150
0
      num = shdr_mem.sh_link;
151
0
    }
152
1
      }
153
59
    else
154
59
      {
155
59
        if (unlikely (elf->state.elf64.scns.cnt == 0))
156
10
    {
157
      /* Cannot use SHN_XINDEX without section headers.  */
158
10
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
159
10
      result = -1;
160
10
      goto out;
161
10
    }
162
163
49
        if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
164
48
    {
165
48
      num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
166
48
      goto success;
167
48
    }
168
169
1
        size_t offset = elf->state.elf64.ehdr->e_shoff;
170
171
1
        if (elf->map_address != NULL
172
1
      && 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
1
        else
194
1
    {
195
      /* We avoid reading in all the section headers.  Just read
196
         the first one.  */
197
1
      Elf64_Shdr shdr_mem;
198
1
      ssize_t r;
199
200
1
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
201
1
              sizeof (Elf64_Shdr), offset))
202
1
        != sizeof (Elf64_Shdr)))
203
1
        {
204
          /* We must be able to read this ELF section header.  */
205
1
          if (r < 0)
206
1
      __libelf_seterrno (ELF_E_INVALID_FILE);
207
0
          else
208
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
209
1
          result = -1;
210
1
          goto out;
211
1
        }
212
213
0
      if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
214
0
        CONVERT (shdr_mem.sh_link);
215
0
      num = shdr_mem.sh_link;
216
0
    }
217
1
      }
218
312
  }
219
220
      /* Store the result.  */
221
9.90k
    success:
222
9.90k
      *dst = num;
223
9.90k
    }
224
225
9.93k
 out:
226
9.93k
  rwlock_unlock (elf->lock);
227
228
9.93k
  return result;
229
9.93k
}
230
INTDEF(elf_getshdrstrndx)
231
/* Alias for the deprecated name.  */
232
strong_alias (elf_getshdrstrndx, elf_getshstrndx)