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