blob: 74a2387a3a0df2ab77534cf98480558285bed483 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* 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 as published by
7 the Free Software Foundation, version 2.
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
33ElfW2(LIBELFBITS,Phdr) *
34elfw2(LIBELFBITS,newphdr) (elf, count)
35 Elf *elf;
36 size_t count;
37{
38 ElfW2(LIBELFBITS,Phdr) *result;
39
40 if (elf == NULL)
41 return NULL;
42
43 if (unlikely (elf->kind != ELF_K_ELF))
44 {
45 __libelf_seterrno (ELF_E_INVALID_HANDLE);
46 return NULL;
47 }
48
49 rwlock_wrlock (elf->lock);
50
51 if (elf->class == 0)
52 elf->class = ELFW(ELFCLASS,LIBELFBITS);
53 else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
54 {
55 __libelf_seterrno (ELF_E_INVALID_CLASS);
56 result = NULL;
57 goto out;
58 }
59
60 if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
61 {
62 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
63 result = NULL;
64 goto out;
65 }
66
67 /* A COUNT of zero means remove existing table. */
68 if (count == 0)
69 {
70 /* Free the old program header. */
71 if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
72 {
73 if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
74 free (elf->state.ELFW(elf,LIBELFBITS).phdr);
75
76 /* Set the pointer to NULL. */
77 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
78 /* Set the `e_phnum' member to the new value. */
79 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
80 /* Also set the size. */
81 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
82 sizeof (ElfW2(LIBELFBITS,Phdr));
83
84 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
85 elf->flags |= ELF_F_DIRTY;
86 __libelf_seterrno (ELF_E_NOERROR);
87 }
88
89 result = NULL;
90 }
91 else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
92 || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
93 {
94 /* Allocate a new program header with the appropriate number of
95 elements. */
96 result = (ElfW2(LIBELFBITS,Phdr) *)
97 realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
98 count * sizeof (ElfW2(LIBELFBITS,Phdr)));
99 if (result == NULL)
100 __libelf_seterrno (ELF_E_NOMEM);
101 else
102 {
103 /* Now set the result. */
104 elf->state.ELFW(elf,LIBELFBITS).phdr = result;
105 /* Clear the whole memory. */
106 memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
107 /* Set the `e_phnum' member to the new value. */
108 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
109 /* Also set the size. */
110 elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
111 elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
112 /* Remember we allocated the array and mark the structure is
113 modified. */
114 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
115 ELF_F_DIRTY | ELF_F_MALLOCED;
116 /* We have to rewrite the entire file if the size of the
117 program header is changed. */
118 elf->flags |= ELF_F_DIRTY;
119 }
120 }
121 else
122 {
123 /* We have the same number of entries. Just clear the array. */
124 assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
125 == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
126
127 /* Mark the structure as modified. */
128 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
129
130 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
131 }
132
133 out:
134 rwlock_unlock (elf->lock);
135
136 return result;
137}
138INTDEF(elfw2(LIBELFBITS,newphdr))