1 /* Append new section. 2 Copyright (C) 1998, 1999, 2000, 2001, 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 <stdbool.h> 24 #include <stddef.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #include "libelfP.h" 29 30 31 Elf_Scn * 32 elf_newscn (elf) 33 Elf *elf; 34 { 35 Elf_Scn *result = NULL; 36 bool first = false; 37 38 if (elf == NULL) 39 return NULL; 40 41 /* We rely on the prefix of the `elf', `elf32', and `elf64' element 42 being the same. */ 43 assert (offsetof (Elf, state.elf.scns_last) 44 == offsetof (Elf, state.elf32.scns_last)); 45 assert (offsetof (Elf, state.elf.scns_last) 46 == offsetof (Elf, state.elf64.scns_last)); 47 assert (offsetof (Elf, state.elf32.scns) 48 == offsetof (Elf, state.elf64.scns)); 49 50 rwlock_wrlock (elf->lock); 51 52 again: 53 if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max) 54 { 55 result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt]; 56 57 if (++elf->state.elf.scns_last->cnt == 1 58 && (elf->state.elf.scns_last 59 == (elf->class == ELFCLASS32 60 || (offsetof (Elf, state.elf32.scns) 61 == offsetof (Elf, state.elf64.scns)) 62 ? &elf->state.elf32.scns : &elf->state.elf64.scns))) 63 /* This is zeroth section. */ 64 first = true; 65 else 66 { 67 assert (elf->state.elf.scns_last->cnt > 1); 68 result->index = result[-1].index + 1; 69 } 70 } 71 else 72 { 73 /* We must allocate a new element. */ 74 Elf_ScnList *newp; 75 76 assert (elf->state.elf.scnincr > 0); 77 78 newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList) 79 + ((elf->state.elf.scnincr *= 2) 80 * sizeof (Elf_Scn)), 1); 81 if (newp == NULL) 82 { 83 __libelf_seterrno (ELF_E_NOMEM); 84 goto out; 85 } 86 87 result = &newp->data[0]; 88 89 /* One section used. */ 90 ++newp->cnt; 91 92 /* This is the number of sections we allocated. */ 93 newp->max = elf->state.elf.scnincr; 94 95 /* Remember the index for the first section in this block. */ 96 newp->data[0].index 97 = 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index; 98 99 /* Enqueue the new list element. */ 100 elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp; 101 } 102 103 /* Create a section header for this section. */ 104 if (elf->class == ELFCLASS32) 105 { 106 result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr)); 107 if (result->shdr.e32 == NULL) 108 { 109 __libelf_seterrno (ELF_E_NOMEM); 110 goto out; 111 } 112 } 113 else 114 { 115 result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr)); 116 if (result->shdr.e64 == NULL) 117 { 118 __libelf_seterrno (ELF_E_NOMEM); 119 goto out; 120 } 121 } 122 123 result->elf = elf; 124 result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED; 125 result->list = elf->state.elf.scns_last; 126 127 /* Initialize the data part. */ 128 result->data_read = 1; 129 if (unlikely (first)) 130 { 131 /* For the first section we mark the data as already available. */ 132 //result->data_list_rear = &result->data_list; 133 first = false; 134 goto again; 135 } 136 137 result->flags |= ELF_F_DIRTY; 138 139 out: 140 rwlock_unlock (elf->lock); 141 142 return result; 143 } 144