• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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