Coverage Report

Created: 2025-08-29 06:11

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