1 /* Append new section. 2 Copyright (C) 1998,1999,2000,2001,2002,2005,2009,2014,2015 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 1998. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of either 8 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 12 13 or 14 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 18 19 or both in parallel, as here. 20 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. 25 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/>. */ 29 30 #ifdef HAVE_CONFIG_H 31 # include <config.h> 32 #endif 33 34 #include <assert.h> 35 #include <stdbool.h> 36 #include <stddef.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "libelfP.h" 41 42 43 Elf_Scn * 44 elf_newscn (Elf *elf) 45 { 46 Elf_Scn *result = NULL; 47 bool first = false; 48 49 if (elf == NULL) 50 return NULL; 51 52 /* We rely on the prefix of the `elf', `elf32', and `elf64' element 53 being the same. */ 54 assert (offsetof (Elf, state.elf.scns_last) 55 == offsetof (Elf, state.elf32.scns_last)); 56 assert (offsetof (Elf, state.elf.scns_last) 57 == offsetof (Elf, state.elf64.scns_last)); 58 assert (offsetof (Elf, state.elf32.scns) 59 == offsetof (Elf, state.elf64.scns)); 60 61 rwlock_wrlock (elf->lock); 62 63 again: 64 if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max) 65 { 66 result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt]; 67 68 if (++elf->state.elf.scns_last->cnt == 1 69 && (elf->state.elf.scns_last 70 == (elf->class == ELFCLASS32 71 || (offsetof (Elf, state.elf32.scns) 72 == offsetof (Elf, state.elf64.scns)) 73 ? &elf->state.elf32.scns : &elf->state.elf64.scns))) 74 /* This is zeroth section. */ 75 first = true; 76 else 77 { 78 assert (elf->state.elf.scns_last->cnt > 1); 79 result->index = result[-1].index + 1; 80 } 81 } 82 else 83 { 84 /* We must allocate a new element. */ 85 Elf_ScnList *newp = NULL; 86 87 assert (elf->state.elf.scnincr > 0); 88 89 if ( 90 #if SIZE_MAX <= 4294967295U 91 likely (elf->state.elf.scnincr 92 < SIZE_MAX / 2 / sizeof (Elf_Scn) - sizeof (Elf_ScnList)) 93 #else 94 1 95 #endif 96 ) 97 newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList) 98 + ((elf->state.elf.scnincr *= 2) 99 * sizeof (Elf_Scn)), 1); 100 if (newp == NULL) 101 { 102 __libelf_seterrno (ELF_E_NOMEM); 103 goto out; 104 } 105 106 result = &newp->data[0]; 107 108 /* One section used. */ 109 ++newp->cnt; 110 111 /* This is the number of sections we allocated. */ 112 newp->max = elf->state.elf.scnincr; 113 114 /* Remember the index for the first section in this block. */ 115 newp->data[0].index 116 = 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index; 117 118 /* Enqueue the new list element. */ 119 elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp; 120 } 121 122 /* Create a section header for this section. */ 123 if (elf->class == ELFCLASS32) 124 { 125 result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr)); 126 if (result->shdr.e32 == NULL) 127 { 128 __libelf_seterrno (ELF_E_NOMEM); 129 goto out; 130 } 131 } 132 else 133 { 134 result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr)); 135 if (result->shdr.e64 == NULL) 136 { 137 __libelf_seterrno (ELF_E_NOMEM); 138 goto out; 139 } 140 } 141 142 result->elf = elf; 143 result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED; 144 result->list = elf->state.elf.scns_last; 145 146 /* Initialize the data part. */ 147 result->data_read = 1; 148 if (unlikely (first)) 149 { 150 /* For the first section we mark the data as already available. */ 151 //result->data_list_rear = &result->data_list; 152 first = false; 153 goto again; 154 } 155 156 result->flags |= ELF_F_DIRTY; 157 158 out: 159 rwlock_unlock (elf->lock); 160 161 return result; 162 } 163