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.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
41 # define LIBELFBITS 32
45 ElfW2(LIBELFBITS,Phdr) *
46 elfw2(LIBELFBITS,newphdr) (elf, count)
50 ElfW2(LIBELFBITS,Phdr) *result;
55 if (unlikely (elf->kind != ELF_K_ELF))
57 __libelf_seterrno (ELF_E_INVALID_HANDLE);
61 if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
63 __libelf_seterrno (ELF_E_INVALID_OPERAND);
67 rwlock_wrlock (elf->lock);
70 elf->class = ELFW(ELFCLASS,LIBELFBITS);
71 else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
73 __libelf_seterrno (ELF_E_INVALID_CLASS);
78 if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
80 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
85 /* A COUNT of zero means remove existing table. */
88 /* Free the old program header. */
89 if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
91 if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
92 free (elf->state.ELFW(elf,LIBELFBITS).phdr);
94 /* Set the pointer to NULL. */
95 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
96 /* Set the `e_phnum' member to the new value. */
97 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
98 /* Also clear any old PN_XNUM extended value. */
99 if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0)
100 elf->state.ELFW(elf,LIBELFBITS).scns.data[0]
101 .shdr.ELFW(e,LIBELFBITS)->sh_info = 0;
102 /* Also set the size. */
103 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
104 sizeof (ElfW2(LIBELFBITS,Phdr));
106 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
107 elf->flags |= ELF_F_DIRTY;
108 __libelf_seterrno (ELF_E_NOERROR);
113 else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
115 || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
117 /* Allocate a new program header with the appropriate number of
119 result = (ElfW2(LIBELFBITS,Phdr) *)
120 realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
121 count * sizeof (ElfW2(LIBELFBITS,Phdr)));
123 __libelf_seterrno (ELF_E_NOMEM);
126 /* Now set the result. */
127 elf->state.ELFW(elf,LIBELFBITS).phdr = result;
128 if (count >= PN_XNUM)
130 /* We have to write COUNT into the zeroth section's sh_info. */
131 Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
132 if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt == 0)
134 assert (elf->state.ELFW(elf,LIBELFBITS).scns.max > 0);
135 elf->state.ELFW(elf,LIBELFBITS).scns.cnt = 1;
137 scn0->shdr.ELFW(e,LIBELFBITS)->sh_info = count;
138 scn0->shdr_flags |= ELF_F_DIRTY;
139 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = PN_XNUM;
142 /* Set the `e_phnum' member to the new value. */
143 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
144 /* Clear the whole memory. */
145 memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
146 /* Also set the size. */
147 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
148 elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
149 /* Remember we allocated the array and mark the structure is
151 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 elf->flags |= ELF_F_DIRTY;
160 /* We have the same number of entries. Just clear the array. */
161 assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
162 == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
164 /* Mark the structure as modified. */
165 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
167 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
168 memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
172 rwlock_unlock (elf->lock);
176 INTDEF(elfw2(LIBELFBITS,newphdr))