Coverage Report

Created: 2026-10-23 06:42

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 <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
26.0k
{
46
26.0k
  int result = 0;
47
48
26.0k
  if (elf == NULL)
49
0
    return -1;
50
51
26.0k
  if (unlikely (elf->kind != ELF_K_ELF))
52
300
    {
53
300
      __libelf_seterrno (ELF_E_INVALID_HANDLE);
54
300
      return -1;
55
300
    }
56
57
25.7k
  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
25.7k
  assert (offsetof (struct Elf, state.elf.ehdr)
62
25.7k
    == offsetof (struct Elf, state.elf32.ehdr));
63
25.7k
  assert (sizeof (elf->state.elf.ehdr)
64
25.7k
    == sizeof (elf->state.elf32.ehdr));
65
25.7k
  assert (offsetof (struct Elf, state.elf.ehdr)
66
25.7k
    == offsetof (struct Elf, state.elf64.ehdr));
67
25.7k
  assert (sizeof (elf->state.elf.ehdr)
68
25.7k
    == sizeof (elf->state.elf64.ehdr));
69
70
25.7k
  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
25.7k
  else
76
25.7k
    {
77
25.7k
      Elf32_Word num;
78
79
25.7k
      num = (elf->class == ELFCLASS32
80
25.7k
       ? elf->state.elf32.ehdr->e_shstrndx
81
25.7k
       : elf->state.elf64.ehdr->e_shstrndx);
82
83
      /* Determine whether the index is too big to fit in the ELF
84
   header.  */
85
25.7k
      if (unlikely (num == SHN_XINDEX))
86
953
  {
87
    /* Yes.  Search the zeroth section header.  */
88
953
    if (elf->class == ELFCLASS32)
89
596
      {
90
596
        size_t offset;
91
596
        if (unlikely (elf->state.elf32.scns.cnt == 0))
92
42
    {
93
      /* Cannot use SHN_XINDEX without section headers.  */
94
42
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
95
42
      result = -1;
96
42
      goto out;
97
42
    }
98
99
554
        if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
100
202
    {
101
202
      num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
102
202
      goto success;
103
202
    }
104
105
352
        offset = elf->state.elf32.ehdr->e_shoff;
106
107
352
        if (elf->map_address != NULL
108
198
      && 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
56
    {
114
      /* First see whether the information in the ELF header is
115
         valid and it does not ask for too much.  */
116
56
      if (unlikely (elf->maximum_size - offset
117
56
        < 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
56
      num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
127
56
           + offset))->sh_link;
128
56
    }
129
296
        else
130
296
    {
131
      /* We avoid reading in all the section headers.  Just read
132
         the first one.  */
133
296
      Elf32_Shdr shdr_mem;
134
296
      ssize_t r;
135
136
296
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
137
296
              sizeof (Elf32_Shdr), offset))
138
296
        != sizeof (Elf32_Shdr)))
139
1
        {
140
          /* We must be able to read this ELF section header.  */
141
1
          if (r < 0)
142
1
      __libelf_seterrno (ELF_E_INVALID_FILE);
143
0
          else
144
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
145
1
          result = -1;
146
1
          goto out;
147
1
        }
148
149
295
      if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
150
225
        CONVERT (shdr_mem.sh_link);
151
295
      num = shdr_mem.sh_link;
152
295
    }
153
352
      }
154
357
    else
155
357
      {
156
357
        if (unlikely (elf->state.elf64.scns.cnt == 0))
157
70
    {
158
      /* Cannot use SHN_XINDEX without section headers.  */
159
70
      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
160
70
      result = -1;
161
70
      goto out;
162
70
    }
163
164
287
        if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
165
114
    {
166
114
      num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
167
114
      goto success;
168
114
    }
169
170
173
        size_t offset = elf->state.elf64.ehdr->e_shoff;
171
172
173
        if (elf->map_address != NULL
173
89
      && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
174
0
      && (ALLOW_UNALIGNED
175
0
          || (((size_t) ((char *) elf->map_address
176
0
         + elf->start_offset + offset))
177
0
        & (__alignof__ (Elf64_Shdr) - 1)) == 0))
178
81
    {
179
      /* First see whether the information in the ELF header is
180
         valid and it does not ask for too much.  */
181
81
      if (unlikely (elf->maximum_size - offset
182
81
        < 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
81
      num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
192
81
           + offset))->sh_link;
193
81
    }
194
92
        else
195
92
    {
196
      /* We avoid reading in all the section headers.  Just read
197
         the first one.  */
198
92
      Elf64_Shdr shdr_mem;
199
92
      ssize_t r;
200
201
92
      if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
202
92
              sizeof (Elf64_Shdr), offset))
203
92
        != sizeof (Elf64_Shdr)))
204
3
        {
205
          /* We must be able to read this ELF section header.  */
206
3
          if (r < 0)
207
3
      __libelf_seterrno (ELF_E_INVALID_FILE);
208
0
          else
209
0
      __libelf_seterrno (ELF_E_INVALID_ELF);
210
3
          result = -1;
211
3
          goto out;
212
3
        }
213
214
89
      if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
215
25
        CONVERT (shdr_mem.sh_link);
216
89
      num = shdr_mem.sh_link;
217
89
    }
218
173
      }
219
953
  }
220
221
      /* Store the result.  */
222
25.6k
    success:
223
25.6k
      *dst = num;
224
25.6k
    }
225
226
25.7k
 out:
227
25.7k
  rwlock_unlock (elf->lock);
228
229
25.7k
  return result;
230
25.7k
}
231
INTDEF(elf_getshdrstrndx)
232
/* Alias for the deprecated name.  */
233
strong_alias (elf_getshdrstrndx, elf_getshstrndx)