Branch data 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 : 171850 : __elf_getphdrnum_rdlock (Elf *elf, size_t *dst)
43 : : {
44 [ - + ]: 171850 : if (unlikely (elf->state.elf64.ehdr == NULL))
45 : : {
46 : : /* Maybe no ELF header was created yet. */
47 : 0 : *dst = 0;
48 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
49 : 0 : return -1;
50 : : }
51 : :
52 : 343700 : *dst = (elf->class == ELFCLASS32
53 : 28392 : ? elf->state.elf32.ehdr->e_phnum
54 [ + + ]: 171850 : : elf->state.elf64.ehdr->e_phnum);
55 : :
56 [ + + ]: 171850 : if (*dst == PN_XNUM)
57 : : {
58 : 12 : const Elf_ScnList *const scns = (elf->class == ELFCLASS32
59 : : ? &elf->state.elf32.scns
60 : : : &elf->state.elf64.scns);
61 : :
62 : : /* If there are no section headers, perhaps this is really just 65536
63 : : written without PN_XNUM support. Either that or it's bad data. */
64 : :
65 [ - + ]: 12 : if (elf->class == ELFCLASS32)
66 : : {
67 [ # # ]: 0 : if (likely (scns->cnt > 0))
68 : : {
69 : 0 : Elf_Scn *scn = &elf->state.elf32.scns.data[0];
70 [ # # ]: 0 : Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn);
71 [ # # ]: 0 : if (shdr)
72 : 0 : *dst = shdr->sh_info;
73 : : }
74 : : }
75 : : else
76 : : {
77 [ - + ]: 12 : if (likely (scns->cnt > 0))
78 : : {
79 : 12 : Elf_Scn *scn = &elf->state.elf64.scns.data[0];
80 [ + + ]: 12 : Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn);
81 [ - + ]: 2 : if (shdr)
82 : 12 : *dst = shdr->sh_info;
83 : : }
84 : : }
85 : : }
86 : :
87 : : return 0;
88 : : }
89 : :
90 : : int
91 : : internal_function
92 : 154880 : __elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst)
93 : : {
94 : 154880 : int result = __elf_getphdrnum_rdlock (elf, dst);
95 : :
96 : : /* If the phdrs haven't been created or read in yet then do some
97 : : sanity checking to make sure phnum and phoff are consistent. */
98 [ + + ]: 154880 : if (elf->state.elf.phdr == NULL)
99 : : {
100 : 32668 : Elf64_Off off = (elf->class == ELFCLASS32
101 : 1938 : ? elf->state.elf32.ehdr->e_phoff
102 [ + + ]: 16334 : : elf->state.elf64.ehdr->e_phoff);
103 [ + + ]: 16334 : if (unlikely (off == 0))
104 : : {
105 : 2462 : *dst = 0;
106 : 2462 : return result;
107 : : }
108 : :
109 [ - + ]: 13872 : if (unlikely (off >= elf->maximum_size))
110 : : {
111 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
112 : 0 : return -1;
113 : : }
114 : :
115 : : /* Check for too many sections. */
116 : 27744 : size_t phdr_size = (elf->class == ELFCLASS32
117 [ + + ]: 13872 : ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr));
118 [ - + ]: 13872 : if (unlikely (*dst > SIZE_MAX / phdr_size))
119 : : {
120 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
121 : 0 : return -1;
122 : : }
123 : :
124 : : /* Truncated file? Don't return more than can be indexed. */
125 [ + - ]: 13872 : if (unlikely (elf->maximum_size - off < *dst * phdr_size))
126 : 0 : *dst = (elf->maximum_size - off) / phdr_size;
127 : : }
128 : :
129 : : return result;
130 : : }
131 : :
132 : : int
133 : 18746 : elf_getphdrnum (Elf *elf, size_t *dst)
134 : : {
135 : 18746 : int result;
136 : :
137 [ - + ]: 18746 : if (elf == NULL)
138 : : return -1;
139 : :
140 [ - + ]: 18746 : if (unlikely (elf->kind != ELF_K_ELF))
141 : : {
142 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
143 : 0 : return -1;
144 : : }
145 : :
146 : 18746 : rwlock_rdlock (elf->lock);
147 : 18746 : result = __elf_getphdrnum_chk_rdlock (elf, dst);
148 : 18746 : rwlock_unlock (elf->lock);
149 : :
150 : 18746 : return result;
151 : : }
|