Branch data Line data Source code
1 : : /* Create new ELF program header table.
2 : : Copyright (C) 1999-2010 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 : 31 : elfw2(LIBELFBITS,newphdr) (elf, count)
47 : : Elf *elf;
48 : : size_t count;
49 : : {
50 : : ElfW2(LIBELFBITS,Phdr) *result;
51 : :
52 [ + - ]: 31 : if (elf == NULL)
53 : : return NULL;
54 : :
55 [ - + ]: 31 : if (unlikely (elf->kind != ELF_K_ELF))
56 : : {
57 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
58 : 0 : return NULL;
59 : : }
60 : :
61 [ - + ]: 31 : if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
62 : : {
63 : 0 : __libelf_seterrno (ELF_E_INVALID_OPERAND);
64 : 0 : return NULL;
65 : : }
66 : :
67 : : rwlock_wrlock (elf->lock);
68 : :
69 [ - + ]: 31 : if (elf->class == 0)
70 : 0 : elf->class = ELFW(ELFCLASS,LIBELFBITS);
71 [ - + ]: 31 : else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
72 : : {
73 : 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
74 : 0 : result = NULL;
75 : 0 : goto out;
76 : : }
77 : :
78 [ - + ]: 31 : if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
79 : : {
80 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
81 : 0 : result = NULL;
82 : 0 : goto out;
83 : : }
84 : :
85 : : /* A COUNT of zero means remove existing table. */
86 [ - + ]: 31 : if (count == 0)
87 : : {
88 : : /* Free the old program header. */
89 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
90 : : {
91 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
92 : 0 : free (elf->state.ELFW(elf,LIBELFBITS).phdr);
93 : :
94 : : /* Set the pointer to NULL. */
95 : 0 : elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
96 : : /* Set the `e_phnum' member to the new value. */
97 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
98 : : /* Also clear any old PN_XNUM extended value. */
99 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0)
100 : : elf->state.ELFW(elf,LIBELFBITS).scns.data[0]
101 : 0 : .shdr.ELFW(e,LIBELFBITS)->sh_info = 0;
102 : : /* Also set the size. */
103 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
104 : : sizeof (ElfW2(LIBELFBITS,Phdr));
105 : :
106 : 0 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
107 : 0 : elf->flags |= ELF_F_DIRTY;
108 : 0 : __libelf_seterrno (ELF_E_NOERROR);
109 : : }
110 : :
111 : : result = NULL;
112 : : }
113 [ + + ]: 31 : else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
114 [ + - ]: 14 : || count == PN_XNUM
115 [ + + ]: 14 : || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
116 : : {
117 : : /* Allocate a new program header with the appropriate number of
118 : : elements. */
119 : 24 : result = (ElfW2(LIBELFBITS,Phdr) *)
120 : 24 : realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
121 : : count * sizeof (ElfW2(LIBELFBITS,Phdr)));
122 [ - + ]: 24 : if (result == NULL)
123 : 0 : __libelf_seterrno (ELF_E_NOMEM);
124 : : else
125 : : {
126 : : /* Now set the result. */
127 : 24 : elf->state.ELFW(elf,LIBELFBITS).phdr = result;
128 [ - + ]: 24 : if (count >= PN_XNUM)
129 : : {
130 : : /* We have to write COUNT into the zeroth section's sh_info. */
131 : 0 : Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
132 [ # # ]: 0 : if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt == 0)
133 : : {
134 [ # # ]: 0 : assert (elf->state.ELFW(elf,LIBELFBITS).scns.max > 0);
135 : 0 : elf->state.ELFW(elf,LIBELFBITS).scns.cnt = 1;
136 : : }
137 : 0 : scn0->shdr.ELFW(e,LIBELFBITS)->sh_info = count;
138 : 0 : scn0->shdr_flags |= ELF_F_DIRTY;
139 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = PN_XNUM;
140 : : }
141 : : else
142 : : /* Set the `e_phnum' member to the new value. */
143 : 24 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
144 : : /* Clear the whole memory. */
145 : 24 : memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
146 : : /* Also set the size. */
147 : 48 : elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
148 : 24 : elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
149 : : /* Remember we allocated the array and mark the structure is
150 : : modified. */
151 : 24 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
152 : : ELF_F_DIRTY | ELF_F_MALLOCED;
153 : : /* We have to rewrite the entire file if the size of the
154 : : program header is changed. */
155 : 24 : elf->flags |= ELF_F_DIRTY;
156 : : }
157 : : }
158 : : else
159 : : {
160 : : /* We have the same number of entries. Just clear the array. */
161 [ - + ]: 7 : assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
162 : : == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
163 : :
164 : : /* Mark the structure as modified. */
165 : 7 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
166 : :
167 : 7 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
168 : 7 : memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
169 : : }
170 : :
171 : : out:
172 : : rwlock_unlock (elf->lock);
173 : :
174 : 31 : return result;
175 : : }
176 : : INTDEF(elfw2(LIBELFBITS,newphdr))
|