1 /*
2  * newscn.c - implementation of the elf_newscn(3) function.
3  * Copyright (C) 1995 - 2006 Michael Riepe
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include <private.h>
21 
22 #ifndef lint
23 static const char rcsid[] = "@(#) $Id: newscn.c,v 1.13 2008/05/23 08:15:35 michael Exp $";
24 #endif /* lint */
25 
26 int
_elf_update_shnum(Elf * elf,size_t shnum)27 _elf_update_shnum(Elf *elf, size_t shnum) {
28     size_t extshnum = 0;
29     Elf_Scn *scn;
30 
31     elf_assert(elf);
32     elf_assert(elf->e_ehdr);
33     scn = elf->e_scn_1;
34     elf_assert(scn);
35     elf_assert(scn->s_index == 0);
36     if (shnum >= SHN_LORESERVE) {
37 	extshnum = shnum;
38 	shnum = 0;
39     }
40     if (elf->e_class == ELFCLASS32) {
41 	((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = shnum;
42 	scn->s_shdr32.sh_size = extshnum;
43     }
44 #if __LIBELF64
45     else if (elf->e_class == ELFCLASS64) {
46 	((Elf64_Ehdr*)elf->e_ehdr)->e_shnum = shnum;
47 	scn->s_shdr64.sh_size = extshnum;
48     }
49 #endif /* __LIBELF64 */
50     else {
51 	if (valid_class(elf->e_class)) {
52 	    seterr(ERROR_UNIMPLEMENTED);
53 	}
54 	else {
55 	    seterr(ERROR_UNKNOWN_CLASS);
56 	}
57 	return -1;
58     }
59     elf->e_ehdr_flags |= ELF_F_DIRTY;
60     scn->s_shdr_flags |= ELF_F_DIRTY;
61     return 0;
62 }
63 
64 static Elf_Scn*
_makescn(Elf * elf,size_t index)65 _makescn(Elf *elf, size_t index) {
66     Elf_Scn *scn;
67 
68     elf_assert(elf);
69     elf_assert(elf->e_magic == ELF_MAGIC);
70     elf_assert(elf->e_ehdr);
71     elf_assert(_elf_scn_init.s_magic == SCN_MAGIC);
72     if (!(scn = (Elf_Scn*)malloc(sizeof(*scn)))) {
73 	seterr(ERROR_MEM_SCN);
74 	return NULL;
75     }
76     *scn = _elf_scn_init;
77     scn->s_elf = elf;
78     scn->s_scn_flags = ELF_F_DIRTY;
79     scn->s_shdr_flags = ELF_F_DIRTY;
80     scn->s_freeme = 1;
81     scn->s_index = index;
82     return scn;
83 }
84 
85 Elf_Scn*
_elf_first_scn(Elf * elf)86 _elf_first_scn(Elf *elf) {
87     Elf_Scn *scn;
88 
89     elf_assert(elf);
90     elf_assert(elf->e_magic == ELF_MAGIC);
91     if ((scn = elf->e_scn_1)) {
92 	return scn;
93     }
94     if ((scn = _makescn(elf, 0))) {
95 	elf->e_scn_1 = elf->e_scn_n = scn;
96 	if (_elf_update_shnum(elf, 1)) {
97 	    free(scn);
98 	    elf->e_scn_1 = elf->e_scn_n = scn = NULL;
99 	}
100     }
101     return scn;
102 }
103 
104 static Elf_Scn*
_buildscn(Elf * elf)105 _buildscn(Elf *elf) {
106     Elf_Scn *scn;
107 
108     if (!_elf_first_scn(elf)) {
109 	return NULL;
110     }
111     scn = elf->e_scn_n;
112     elf_assert(scn);
113     if (!(scn = _makescn(elf, scn->s_index + 1))) {
114 	return NULL;
115     }
116     if (_elf_update_shnum(elf, scn->s_index + 1)) {
117 	free(scn);
118 	return NULL;
119     }
120     elf->e_scn_n = elf->e_scn_n->s_link = scn;
121     return scn;
122 }
123 
124 Elf_Scn*
elf_newscn(Elf * elf)125 elf_newscn(Elf *elf) {
126     Elf_Scn *scn;
127 
128     if (!elf) {
129 	return NULL;
130     }
131     elf_assert(elf->e_magic == ELF_MAGIC);
132     if (!elf->e_readable && !elf->e_ehdr) {
133 	seterr(ERROR_NOEHDR);
134     }
135     else if (elf->e_kind != ELF_K_ELF) {
136 	seterr(ERROR_NOTELF);
137     }
138     else if (!elf->e_ehdr && !_elf_cook(elf)) {
139 	return NULL;
140     }
141     else if ((scn = _buildscn(elf))) {
142 	return scn;
143     }
144     return NULL;
145 }
146