Branch data 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 : 2698817 : elf_newdata (Elf_Scn *scn)
42 : : {
43 : 2698817 : Elf_Data_List *result = NULL;
44 : :
45 [ + - ]: 2698817 : if (scn == NULL)
46 : : return NULL;
47 : :
48 [ - + ]: 2698817 : 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 : 5397634 : if (scn->elf->class == ELFCLASS32
56 : : || (offsetof (struct Elf, state.elf32.ehdr)
57 : : == offsetof (struct Elf, state.elf64.ehdr))
58 [ - + ]: 2698817 : ? 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 : 2698817 : 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 [ + + ]: 2698817 : if (scn->data_read
82 [ + + ]: 2698812 : && scn->rawdata_base != NULL
83 [ + + ]: 31 : && scn->data_list_rear == NULL)
84 : 7 : __libelf_set_data_list_rdlock (scn, 1);
85 : :
86 [ + + ][ + + ]: 2698817 : 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 : 2698723 : result = &scn->data_list;
91 : 2698723 : 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 : 2698817 : result->data.d.d_version = EV_CURRENT;
121 : :
122 : 2698817 : result->data.s = scn;
123 : :
124 : : /* Add to the end of the list. */
125 [ + + ]: 2698817 : if (scn->data_list_rear != NULL)
126 : 94 : scn->data_list_rear->next = result;
127 : :
128 : 2698817 : scn->data_list_rear = result;
129 : :
130 : 2698817 : out:
131 : 2698817 : 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 : 2698817 : return &result->data.d;
136 : : }
|