Line data Source code
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@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 2697683 : elf_newscn (Elf *elf)
45 : {
46 2697683 : Elf_Scn *result = NULL;
47 2697683 : bool first = false;
48 :
49 2697683 : 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 2698087 : again:
64 2698087 : if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max)
65 : {
66 2697196 : result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt];
67 :
68 2697196 : if (++elf->state.elf.scns_last->cnt == 1
69 808 : && (elf->state.elf.scns_last
70 : == (elf->class == ELFCLASS32
71 : || (offsetof (Elf, state.elf32.scns)
72 : == offsetof (Elf, state.elf64.scns))
73 404 : ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
74 : /* This is zeroth section. */
75 : first = true;
76 : else
77 : {
78 2696792 : assert (elf->state.elf.scns_last->cnt > 1);
79 2696792 : result->index = result[-1].index + 1;
80 : }
81 : }
82 : else
83 : {
84 : /* We must allocate a new element. */
85 891 : Elf_ScnList *newp = NULL;
86 :
87 891 : 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 891 : newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList)
98 891 : + ((elf->state.elf.scnincr *= 2)
99 891 : * sizeof (Elf_Scn)), 1);
100 891 : if (newp == NULL)
101 : {
102 0 : __libelf_seterrno (ELF_E_NOMEM);
103 0 : goto out;
104 : }
105 :
106 891 : result = &newp->data[0];
107 :
108 : /* One section used. */
109 891 : ++newp->cnt;
110 :
111 : /* This is the number of sections we allocated. */
112 891 : newp->max = elf->state.elf.scnincr;
113 :
114 : /* Remember the index for the first section in this block. */
115 : newp->data[0].index
116 891 : = 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index;
117 :
118 : /* Enqueue the new list element. */
119 891 : elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp;
120 : }
121 :
122 : /* Create a section header for this section. */
123 2698087 : if (elf->class == ELFCLASS32)
124 : {
125 1577840 : result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr));
126 1577840 : if (result->shdr.e32 == NULL)
127 : {
128 0 : __libelf_seterrno (ELF_E_NOMEM);
129 0 : goto out;
130 : }
131 : }
132 : else
133 : {
134 1120247 : result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr));
135 1120247 : if (result->shdr.e64 == NULL)
136 : {
137 0 : __libelf_seterrno (ELF_E_NOMEM);
138 0 : goto out;
139 : }
140 : }
141 :
142 2698087 : result->elf = elf;
143 2698087 : result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
144 2698087 : result->list = elf->state.elf.scns_last;
145 :
146 : /* Initialize the data part. */
147 2698087 : result->data_read = 1;
148 2698087 : 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 2697683 : result->flags |= ELF_F_DIRTY;
157 :
158 : out:
159 : rwlock_unlock (elf->lock);
160 :
161 : return result;
162 : }
|