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