05aa7a17a1fac7b2120db4dff63da8f6f554431d
[platform/upstream/rpm.git] / elfutils / libelf / elf32_newphdr.c
1 /* Create new ELF program header table.
2    Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2 as
7    published by the Free Software Foundation.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "libelfP.h"
27
28 #ifndef LIBELFBITS
29 # define LIBELFBITS 32
30 #endif
31
32
33 ElfW2(LIBELFBITS,Phdr) *
34 elfw2(LIBELFBITS,newphdr) (Elf *elf, size_t count)
35 {
36   ElfW2(LIBELFBITS,Phdr) *result;
37
38   if (elf == NULL)
39     return NULL;
40
41   if (unlikely (elf->kind != ELF_K_ELF))
42     {
43       __libelf_seterrno (ELF_E_INVALID_HANDLE);
44       return NULL;
45     }
46
47   rwlock_wrlock (elf->lock);
48
49   if (elf->class == 0)
50     elf->class = ELFW(ELFCLASS,LIBELFBITS);
51   else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
52     {
53       __libelf_seterrno (ELF_E_INVALID_CLASS);
54       result = NULL;
55       goto out;
56     }
57
58   if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
59     {
60       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
61       result = NULL;
62       goto out;
63     }
64
65   /* A COUNT of zero means remove existing table.  */
66   if (count == 0)
67     {
68       /* Free the old program header.  */
69       if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
70         {
71           if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
72             free (elf->state.ELFW(elf,LIBELFBITS).phdr);
73
74           /* Set the pointer to NULL.  */
75           elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
76           /* Set the `e_phnum' member to the new value.  */
77           elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
78           /* Also set the size.  */
79           elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
80             sizeof (ElfW2(LIBELFBITS,Phdr));
81
82           elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
83           elf->flags |= ELF_F_DIRTY;
84           __libelf_seterrno (ELF_E_NOERROR);
85         }
86
87       result = NULL;
88     }
89   else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count)
90     {
91       /* Allocate a new program header with the appropriate number of
92          elements.  */
93       result = (ElfW2(LIBELFBITS,Phdr) *)
94         realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
95                  count * sizeof (ElfW2(LIBELFBITS,Phdr)));
96       if (result == NULL)
97         __libelf_seterrno (ELF_E_NOMEM);
98       else
99         {
100           /* Now set the result.  */
101           elf->state.ELFW(elf,LIBELFBITS).phdr = result;
102           /* Clear the whole memory.  */
103           memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
104           /* Set the `e_phnum' member to the new value.  */
105           elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
106           /* Also set the size.  */
107           elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
108             elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
109           /* Remember we allocated the array and mark the structure is
110              modified.  */
111           elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
112             ELF_F_DIRTY | ELF_F_MALLOCED;
113           /* We have to rewrite the entire file if the size of the
114              program header is changed.  */
115           elf->flags |= ELF_F_DIRTY;
116         }
117     }
118   else
119     {
120       /* We have the same number of entries.  Just clear the array.  */
121       assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
122               == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
123
124       /* Mark the structure as modified.  */
125       elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
126
127       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
128     }
129
130  out:
131   rwlock_unlock (elf->lock);
132
133   return result;
134 }
135 INTDEF(elfw2(LIBELFBITS,newphdr))