Line data Source code
1 : /* Return number of program headers in the ELF file.
2 : Copyright (C) 2010, 2014, 2015, 2016 Red Hat, Inc.
3 : This file is part of elfutils.
4 :
5 : This file is free software; you can redistribute it and/or modify
6 : it under the terms of either
7 :
8 : * the GNU Lesser General Public License as published by the Free
9 : Software Foundation; either version 3 of the License, or (at
10 : your option) any later version
11 :
12 : or
13 :
14 : * the GNU General Public License as published by the Free
15 : Software Foundation; either version 2 of the License, or (at
16 : your option) any later version
17 :
18 : or both in parallel, as here.
19 :
20 : elfutils is distributed in the hope that it will be useful, but
21 : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : General Public License for more details.
24 :
25 : You should have received copies of the GNU General Public License and
26 : the GNU Lesser General Public License along with this program. If
27 : not, see <http://www.gnu.org/licenses/>. */
28 :
29 : #ifdef HAVE_CONFIG_H
30 : # include <config.h>
31 : #endif
32 :
33 : #include <assert.h>
34 : #include <gelf.h>
35 : #include <stddef.h>
36 :
37 : #include "libelfP.h"
38 :
39 :
40 : int
41 : internal_function
42 72249 : __elf_getphdrnum_rdlock (Elf *elf, size_t *dst)
43 : {
44 72249 : if (unlikely (elf->state.elf64.ehdr == NULL))
45 : {
46 : /* Maybe no ELF header was created yet. */
47 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
48 0 : return -1;
49 : }
50 :
51 144498 : *dst = (elf->class == ELFCLASS32
52 14176 : ? elf->state.elf32.ehdr->e_phnum
53 72249 : : elf->state.elf64.ehdr->e_phnum);
54 :
55 72249 : if (*dst == PN_XNUM)
56 : {
57 6 : const Elf_ScnList *const scns = (elf->class == ELFCLASS32
58 : ? &elf->state.elf32.scns
59 : : &elf->state.elf64.scns);
60 :
61 : /* If there are no section headers, perhaps this is really just 65536
62 : written without PN_XNUM support. Either that or it's bad data. */
63 :
64 6 : if (elf->class == ELFCLASS32)
65 : {
66 0 : if (likely (scns->cnt > 0))
67 : {
68 0 : Elf_Scn *scn = &elf->state.elf32.scns.data[0];
69 0 : Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn);
70 0 : if (shdr)
71 0 : *dst = shdr->sh_info;
72 : }
73 : }
74 : else
75 : {
76 6 : if (likely (scns->cnt > 0))
77 : {
78 6 : Elf_Scn *scn = &elf->state.elf64.scns.data[0];
79 6 : Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn);
80 6 : if (shdr)
81 6 : *dst = shdr->sh_info;
82 : }
83 : }
84 : }
85 :
86 : return 0;
87 : }
88 :
89 : int
90 : internal_function
91 64467 : __elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst)
92 : {
93 64467 : int result = __elf_getphdrnum_rdlock (elf, dst);
94 :
95 : /* If the phdrs haven't been created or read in yet then do some
96 : sanity checking to make sure phnum and phoff are consistent. */
97 64467 : if (elf->state.elf.phdr == NULL)
98 : {
99 15350 : Elf64_Off off = (elf->class == ELFCLASS32
100 773 : ? elf->state.elf32.ehdr->e_phoff
101 7675 : : elf->state.elf64.ehdr->e_phoff);
102 7675 : if (unlikely (off == 0))
103 : {
104 1236 : *dst = 0;
105 1236 : return result;
106 : }
107 :
108 6439 : if (unlikely (off >= elf->maximum_size))
109 : {
110 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
111 0 : return -1;
112 : }
113 :
114 : /* Check for too many sections. */
115 12878 : size_t phdr_size = (elf->class == ELFCLASS32
116 6439 : ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr));
117 6439 : if (unlikely (*dst > SIZE_MAX / phdr_size))
118 : {
119 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
120 0 : return -1;
121 : }
122 :
123 : /* Truncated file? Don't return more than can be indexed. */
124 6439 : if (unlikely (elf->maximum_size - off < *dst * phdr_size))
125 0 : *dst = (elf->maximum_size - off) / phdr_size;
126 : }
127 :
128 : return result;
129 : }
130 :
131 : int
132 8705 : elf_getphdrnum (Elf *elf, size_t *dst)
133 : {
134 8705 : int result;
135 :
136 8705 : if (elf == NULL)
137 : return -1;
138 :
139 8705 : if (unlikely (elf->kind != ELF_K_ELF))
140 : {
141 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
142 0 : return -1;
143 : }
144 :
145 8705 : rwlock_rdlock (elf->lock);
146 8705 : result = __elf_getphdrnum_chk_rdlock (elf, dst);
147 8705 : rwlock_unlock (elf->lock);
148 :
149 8705 : return result;
150 : }
|