Elfutils fiddles fo fix striptofile.
[platform/upstream/rpm.git] / elfutils / libelf / elf_newscn.c
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 version 2 as
7    published by the Free Software Foundation.
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 *
32 elf_newscn (Elf *elf)
33 {
34   Elf_Scn *result = NULL;
35   bool first = false;
36
37   if (elf == NULL)
38     return NULL;
39
40   /* We rely on the prefix of the `elf', `elf32', and `elf64' element
41      being the same.  */
42   assert (offsetof (Elf, state.elf.scns_last)
43           == offsetof (Elf, state.elf32.scns_last));
44   assert (offsetof (Elf, state.elf.scns_last)
45           == offsetof (Elf, state.elf64.scns_last));
46   assert (offsetof (Elf, state.elf32.scns)
47           == offsetof (Elf, state.elf64.scns));
48
49   rwlock_wrlock (elf->lock);
50
51  again:
52   if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max)
53     {
54       result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt];
55
56       if (++elf->state.elf.scns_last->cnt == 1
57           && (elf->state.elf.scns_last
58               == (elf->class == ELFCLASS32
59                   || (offsetof (Elf, state.elf32.scns)
60                       == offsetof (Elf, state.elf64.scns))
61                   ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
62         /* This is zeroth section.  */
63         first = true;
64       else
65         {
66           assert (elf->state.elf.scns_last->cnt > 1);
67           result->index = result[-1].index + 1;
68         }
69     }
70   else
71     {
72       /* We must allocate a new element.  */
73       Elf_ScnList *newp;
74
75       assert (elf->state.elf.scnincr > 0);
76
77       newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList)
78                                      + ((elf->state.elf.scnincr *= 2)
79                                         * sizeof (Elf_Scn)), 1);
80       if (newp == NULL)
81         {
82           __libelf_seterrno (ELF_E_NOMEM);
83           goto out;
84         }
85
86       result = &newp->data[0];
87
88       /* One section used.  */
89       ++newp->cnt;
90
91       /* This is the number of sections we allocated.  */
92       newp->max = elf->state.elf.scnincr;
93
94       /* Remember the index for the first section in this block.  */
95       newp->data[0].index
96         = 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index;
97
98       /* Enqueue the new list element.  */
99       elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp;
100     }
101
102   /* Create a section header for this section.  */
103   if (elf->class == ELFCLASS32)
104     {
105       result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr));
106       if (result->shdr.e32 == NULL)
107         {
108           __libelf_seterrno (ELF_E_NOMEM);
109           goto out;
110         }
111     }
112   else
113     {
114       result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr));
115       if (result->shdr.e64 == NULL)
116         {
117           __libelf_seterrno (ELF_E_NOMEM);
118           goto out;
119         }
120     }
121
122   result->elf = elf;
123   result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
124   result->list = elf->state.elf.scns_last;
125
126   /* Initialize the data part.  */
127   result->data_read = 1;
128   if (unlikely (first))
129     {
130       /* For the first section we mark the data as already available.  */
131       //result->data_list_rear = &result->data_list;
132       first = false;
133       goto again;
134     }
135
136   result->flags |= ELF_F_DIRTY;
137
138  out:
139   rwlock_unlock (elf->lock);
140
141   return result;
142 }