Line data Source code
1 : /* Create new, empty section data.
2 : Copyright (C) 1998, 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Contributed 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 <stddef.h>
35 : #include <stdlib.h>
36 :
37 : #include "libelfP.h"
38 :
39 :
40 : Elf_Data *
41 2632184 : elf_newdata (Elf_Scn *scn)
42 : {
43 2632184 : Elf_Data_List *result = NULL;
44 :
45 2632184 : if (scn == NULL)
46 : return NULL;
47 :
48 2632184 : if (unlikely (scn->index == 0))
49 : {
50 : /* It is not allowed to add something to the 0th section. */
51 0 : __libelf_seterrno (ELF_E_NOT_NUL_SECTION);
52 0 : return NULL;
53 : }
54 :
55 2632184 : if (scn->elf->class == ELFCLASS32
56 : || (offsetof (struct Elf, state.elf32.ehdr)
57 : == offsetof (struct Elf, state.elf64.ehdr))
58 2632184 : ? scn->elf->state.elf32.ehdr == NULL
59 : : scn->elf->state.elf64.ehdr == NULL)
60 : {
61 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
62 0 : return NULL;
63 : }
64 :
65 : rwlock_wrlock (scn->elf->lock);
66 :
67 : /* data_read is set when data has been read from the ELF image or
68 : when a new section has been created by elf_newscn. If data has
69 : been read from the ELF image, then rawdata_base will point to raw
70 : data. If data_read has been set by elf_newscn, then rawdata_base
71 : will be NULL. data_list_rear will be set by elf_getdata if the
72 : data has been converted, or by this function, elf_newdata, when
73 : new data has been added.
74 :
75 : Currently elf_getdata and elf_update rely on the fact that when
76 : data_list_read is not NULL all they have to do is walk the data
77 : list. They will ignore any (unread) raw data in that case.
78 :
79 : So we need to make sure the data list is setup if there is
80 : already data available. */
81 2632184 : if (scn->data_read
82 2632179 : && scn->rawdata_base != NULL
83 31 : && scn->data_list_rear == NULL)
84 7 : __libelf_set_data_list_rdlock (scn, 1);
85 :
86 2632184 : if (scn->data_read && scn->data_list_rear == NULL)
87 : {
88 : /* This means the section was created by the user and this is the
89 : first data. */
90 2632090 : result = &scn->data_list;
91 2632090 : result->flags = ELF_F_DIRTY;
92 : }
93 : else
94 : {
95 : /* It would be more efficient to create new data without
96 : reading/converting the data from the file. But then we
97 : have to remember this. Currently elf_getdata and
98 : elf_update rely on the fact that they don't have to
99 : load/convert any data if data_list_rear is set. */
100 94 : if (scn->data_read == 0)
101 : {
102 5 : if (__libelf_set_rawdata_wrlock (scn) != 0)
103 : /* Something went wrong. The error value is already set. */
104 : goto out;
105 5 : __libelf_set_data_list_rdlock (scn, 1);
106 : }
107 :
108 : /* Create a new, empty data descriptor. */
109 94 : result = (Elf_Data_List *) calloc (1, sizeof (Elf_Data_List));
110 94 : if (result == NULL)
111 : {
112 0 : __libelf_seterrno (ELF_E_NOMEM);
113 0 : goto out;
114 : }
115 :
116 94 : result->flags = ELF_F_DIRTY | ELF_F_MALLOCED;
117 : }
118 :
119 : /* Set the predefined values. */
120 2632184 : result->data.d.d_version = __libelf_version;
121 :
122 2632184 : result->data.s = scn;
123 :
124 : /* Add to the end of the list. */
125 2632184 : if (scn->data_list_rear != NULL)
126 94 : scn->data_list_rear->next = result;
127 :
128 2632184 : scn->data_list_rear = result;
129 :
130 2632184 : out:
131 : rwlock_unlock (scn->elf->lock);
132 :
133 : /* Please note that the following is thread safe and is also defined
134 : for RESULT == NULL since it still return NULL. */
135 2632184 : return &result->data.d;
136 : }
|