Branch data Line data Source code
1 : : /* Create new ELF program header table.
2 : : Copyright (C) 1999-2010, 2014, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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 <stdlib.h>
36 : : #include <string.h>
37 : :
38 : : #include "libelfP.h"
39 : :
40 : : #ifndef LIBELFBITS
41 : : # define LIBELFBITS 32
42 : : #endif
43 : :
44 : :
45 : : ElfW2(LIBELFBITS,Phdr) *
46 : 398 : elfw2(LIBELFBITS,newphdr) (Elf *elf, size_t count)
47 : : {
48 : 398 : ElfW2(LIBELFBITS,Phdr) *result;
49 : :
50 [ - + ]: 398 : if (elf == NULL)
51 : : return NULL;
52 : :
53 [ - + ]: 398 : if (unlikely (elf->kind != ELF_K_ELF))
54 : : {
55 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
56 : 0 : return NULL;
57 : : }
58 : :
59 : : /* This check is correct, it is for sh_info, which is either
60 : : Elf32_Word or Elf64_Word, both being 32 bits. But count is size_t
61 : : so might not fit on 32bit ELF files. */
62 [ - + ]: 398 : if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
63 : : {
64 : 0 : __libelf_seterrno (ELF_E_INVALID_OPERAND);
65 : 0 : return NULL;
66 : : }
67 : :
68 : 398 : rwlock_wrlock (elf->lock);
69 : :
70 [ - + ]: 398 : if (elf->class == 0)
71 : 0 : elf->class = ELFW(ELFCLASS,LIBELFBITS);
72 [ - + ]: 398 : else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
73 : : {
74 : 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
75 : 0 : result = NULL;
76 : 0 : goto out;
77 : : }
78 : :
79 [ - + ]: 398 : if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
80 : : {
81 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
82 : 0 : result = NULL;
83 : 0 : goto out;
84 : : }
85 : :
86 : : /* A COUNT of zero means remove existing table. */
87 [ - + ]: 398 : if (count == 0)
88 : : {
89 : : /* Free the old program header. */
90 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
91 : : {
92 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
93 : 0 : free (elf->state.ELFW(elf,LIBELFBITS).phdr);
94 : :
95 : : /* Set the pointer to NULL. */
96 : 0 : elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
97 : : /* Set the `e_phnum' member to the new value. */
98 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
99 : : /* Also clear any old PN_XNUM extended value. */
100 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0)
101 : 0 : elf->state.ELFW(elf,LIBELFBITS).scns.data[0]
102 : 0 : .shdr.ELFW(e,LIBELFBITS)->sh_info = 0;
103 : : /* Also set the size. */
104 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
105 : : sizeof (ElfW2(LIBELFBITS,Phdr));
106 : :
107 : 0 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
108 : 0 : elf->flags |= ELF_F_DIRTY;
109 : 0 : __libelf_seterrno (ELF_E_NOERROR);
110 : : }
111 : :
112 : : result = NULL;
113 : : }
114 [ + + ]: 398 : else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
115 [ + - ]: 57 : || count == PN_XNUM
116 [ + + ]: 57 : || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
117 : : {
118 [ - + ]: 386 : if (unlikely (count > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))))
119 : : {
120 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX);
121 : 0 : result = NULL;
122 : 0 : goto out;
123 : : }
124 : :
125 : 386 : Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
126 [ - + - - ]: 386 : if (unlikely (count >= PN_XNUM && scn0->shdr.ELFW(e,LIBELFBITS) == NULL))
127 : : {
128 : : /* Something is wrong with section zero, but we need it to write
129 : : the extended phdr count. */
130 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
131 : 0 : result = NULL;
132 : 0 : goto out;
133 : : }
134 : :
135 : : /* Allocate a new program header with the appropriate number of
136 : : elements. */
137 : 386 : result = (ElfW2(LIBELFBITS,Phdr) *)
138 : 386 : realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
139 : : count * sizeof (ElfW2(LIBELFBITS,Phdr)));
140 [ - + ]: 386 : if (result == NULL)
141 : 0 : __libelf_seterrno (ELF_E_NOMEM);
142 : : else
143 : : {
144 : : /* Now set the result. */
145 : 386 : elf->state.ELFW(elf,LIBELFBITS).phdr = result;
146 [ - + ]: 386 : if (count >= PN_XNUM)
147 : : {
148 : : /* We have to write COUNT into the zeroth section's sh_info. */
149 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt == 0)
150 : : {
151 [ # # ]: 0 : assert (elf->state.ELFW(elf,LIBELFBITS).scns.max > 0);
152 : 0 : elf->state.ELFW(elf,LIBELFBITS).scns.cnt = 1;
153 : : }
154 : 0 : scn0->shdr.ELFW(e,LIBELFBITS)->sh_info = count;
155 : 0 : scn0->shdr_flags |= ELF_F_DIRTY;
156 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = PN_XNUM;
157 : : }
158 : : else
159 : : /* Set the `e_phnum' member to the new value. */
160 : 386 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
161 : : /* Clear the whole memory. */
162 : 386 : memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
163 : : /* Also set the size. */
164 : 386 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
165 : 386 : elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
166 : : /* Remember we allocated the array and mark the structure is
167 : : modified. */
168 : 386 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
169 : : ELF_F_DIRTY | ELF_F_MALLOCED;
170 : : /* We have to rewrite the entire file if the size of the
171 : : program header is changed. */
172 : 386 : elf->flags |= ELF_F_DIRTY;
173 : : }
174 : : }
175 : : else
176 : : {
177 : : /* We have the same number of entries. Just clear the array. */
178 [ - + ]: 12 : assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
179 : : == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
180 : :
181 : : /* Mark the structure as modified. */
182 : 12 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
183 : :
184 : 12 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
185 : 12 : memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
186 : : }
187 : :
188 : : out:
189 : : rwlock_unlock (elf->lock);
190 : :
191 : : return result;
192 : : }
193 : : INTDEF(elfw2(LIBELFBITS,newphdr))
|