1 /* Append new section.
2 Copyright (C) 1998, 1999, 2000, 2001, 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 <stdbool.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "libelfP.h"
29
30
31 Elf_Scn *
elf_newscn(elf)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