1 /* Create new ELF program header table. 2 Copyright (C) 1999, 2000, 2002 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) 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 33 ElfW2(LIBELFBITS,Phdr) * 34 elfw2(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 } 138 INTDEF(elfw2(LIBELFBITS,newphdr)) 139