1 /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
2 /* $OpenBSD: loadfile_elf.c,v 1.17 2020/10/26 04:04:31 visa Exp $ */
3
4 /*-
5 * Copyright (c) 1997 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center and by Christos Zoulas.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1992, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * This code is derived from software contributed to Berkeley by
39 * Ralph Campbell.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)boot.c 8.1 (Berkeley) 6/10/93
66 */
67
68 #include <lib/libsa/arc4.h>
69
70 int ELFNAME(exec)(int, Elf_Ehdr *, uint64_t *, int);
71
72 int
ELFNAME(exec)73 ELFNAME(exec)(int fd, Elf_Ehdr *elf, uint64_t *marks, int flags)
74 {
75 Elf_Shdr *shp;
76 Elf_Phdr *phdr;
77 Elf_Off off;
78 int i;
79 size_t sz;
80 int first;
81 int havesyms;
82 paddr_t minp = ~0, maxp = 0, pos = 0;
83 paddr_t offset = marks[MARK_START], shpp, elfp;
84
85 sz = elf->e_phnum * sizeof(Elf_Phdr);
86 phdr = ALLOC(sz);
87
88 if (lseek(fd, (off_t)elf->e_phoff, SEEK_SET) == -1) {
89 WARN(("lseek phdr"));
90 FREE(phdr, sz);
91 return 1;
92 }
93 if (read(fd, phdr, sz) != sz) {
94 WARN(("read program headers"));
95 FREE(phdr, sz);
96 return 1;
97 }
98
99 for (first = 1, i = 0; i < elf->e_phnum; i++) {
100 if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) {
101
102 /* Fill segment if asked for. */
103 if (flags & LOAD_RANDOM) {
104 extern struct rc4_ctx randomctx;
105
106 rc4_getbytes(&randomctx,
107 (void *)LOADADDR(phdr[i].p_paddr),
108 phdr[i].p_filesz);
109 }
110 if (flags & (LOAD_RANDOM | COUNT_RANDOM)) {
111 marks[MARK_RANDOM] = LOADADDR(phdr[i].p_paddr);
112 marks[MARK_ERANDOM] =
113 marks[MARK_RANDOM] + phdr[i].p_filesz;
114 }
115 continue;
116 }
117
118 if (phdr[i].p_type != PT_LOAD ||
119 (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
120 continue;
121
122 #ifdef CHECK_PHDR
123 if (CHECK_PHDR(ELFSIZE, &phdr[i])) {
124 FREE(phdr, sz);
125 return 1;
126 }
127 #endif
128
129 #define IS_TEXT(p) (p.p_flags & PF_X)
130 #define IS_DATA(p) ((p.p_flags & PF_X) == 0)
131 #define IS_BSS(p) (p.p_filesz < p.p_memsz)
132 /*
133 * XXX: Assume first address is lowest
134 */
135 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
136 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
137
138 /* Read in segment. */
139 PROGRESS(("%s%lu", first ? "" : "+",
140 (u_long)phdr[i].p_filesz));
141
142 if (lseek(fd, (off_t)phdr[i].p_offset, SEEK_SET) == -1) {
143 WARN(("lseek text"));
144 FREE(phdr, sz);
145 return 1;
146 }
147 if (READ(fd, phdr[i].p_paddr, phdr[i].p_filesz) !=
148 phdr[i].p_filesz) {
149 WARN(("read text"));
150 FREE(phdr, sz);
151 return 1;
152 }
153
154 first = 0;
155 }
156
157 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) ||
158 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA | COUNT_TEXT)))) {
159 pos = phdr[i].p_paddr;
160 if (minp > pos)
161 minp = pos;
162 pos += phdr[i].p_filesz;
163 if (maxp < pos)
164 maxp = pos;
165 }
166
167 /* Zero out BSS. */
168 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
169 PROGRESS(("+%lu",
170 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
171 BZERO((phdr[i].p_paddr + phdr[i].p_filesz),
172 phdr[i].p_memsz - phdr[i].p_filesz);
173 }
174 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
175 pos += phdr[i].p_memsz - phdr[i].p_filesz;
176 if (maxp < pos)
177 maxp = pos;
178 }
179 }
180 FREE(phdr, sz);
181
182 /*
183 * Copy the ELF and section headers.
184 */
185 elfp = maxp = roundup(maxp, sizeof(Elf_Addr));
186 if (flags & (LOAD_HDR | COUNT_HDR))
187 maxp += sizeof(Elf_Ehdr);
188
189 if (flags & (LOAD_SYM | COUNT_SYM)) {
190 if (lseek(fd, (off_t)elf->e_shoff, SEEK_SET) == -1) {
191 WARN(("lseek section headers"));
192 return 1;
193 }
194 sz = elf->e_shnum * sizeof(Elf_Shdr);
195 shp = ALLOC(sz);
196
197 if (read(fd, shp, sz) != sz) {
198 WARN(("read section headers"));
199 FREE(shp, sz);
200 return 1;
201 }
202
203 shpp = maxp;
204 maxp += roundup(sz, sizeof(Elf_Addr));
205
206 size_t shstrsz = shp[elf->e_shstrndx].sh_size;
207 char *shstr = ALLOC(shstrsz);
208 if (lseek(fd, (off_t)shp[elf->e_shstrndx].sh_offset, SEEK_SET) == -1) {
209 WARN(("lseek section header string table"));
210 FREE(shstr, shstrsz);
211 FREE(shp, sz);
212 return 1;
213 }
214 if (read(fd, shstr, shstrsz) != shstrsz) {
215 WARN(("read section header string table"));
216 FREE(shstr, shstrsz);
217 FREE(shp, sz);
218 return 1;
219 }
220
221 /*
222 * Now load the symbol sections themselves. Make sure the
223 * sections are aligned. Don't bother with string tables if
224 * there are no symbol sections.
225 */
226 off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr));
227
228 for (havesyms = i = 0; i < elf->e_shnum; i++)
229 if (shp[i].sh_type == SHT_SYMTAB)
230 havesyms = 1;
231
232 for (first = 1, i = 0; i < elf->e_shnum; i++) {
233 if (shp[i].sh_type == SHT_SYMTAB ||
234 shp[i].sh_type == SHT_STRTAB ||
235 !strcmp(shstr + shp[i].sh_name, ".debug_line") ||
236 !strcmp(shstr + shp[i].sh_name, ELF_CTF)) {
237 if (havesyms && (flags & LOAD_SYM)) {
238 PROGRESS(("%s%ld", first ? " [" : "+",
239 (u_long)shp[i].sh_size));
240 if (lseek(fd, (off_t)shp[i].sh_offset,
241 SEEK_SET) == -1) {
242 WARN(("lseek symbols"));
243 FREE(shstr, shstrsz);
244 FREE(shp, sz);
245 return 1;
246 }
247 if (READ(fd, maxp, shp[i].sh_size) !=
248 shp[i].sh_size) {
249 WARN(("read symbols"));
250 FREE(shstr, shstrsz);
251 FREE(shp, sz);
252 return 1;
253 }
254 }
255 maxp += roundup(shp[i].sh_size,
256 sizeof(Elf_Addr));
257 shp[i].sh_offset = off;
258 shp[i].sh_flags |= SHF_ALLOC;
259 off += roundup(shp[i].sh_size, sizeof(Elf_Addr));
260 first = 0;
261 }
262 }
263 if (flags & LOAD_SYM) {
264 BCOPY(shp, shpp, sz);
265
266 if (havesyms && first == 0)
267 PROGRESS(("]"));
268 }
269 FREE(shstr, shstrsz);
270 FREE(shp, sz);
271 }
272
273 /*
274 * Frob the copied ELF header to give information relative
275 * to elfp.
276 */
277 if (flags & LOAD_HDR) {
278 elf->e_phoff = 0;
279 elf->e_shoff = sizeof(Elf_Ehdr);
280 elf->e_phentsize = 0;
281 elf->e_phnum = 0;
282 BCOPY(elf, elfp, sizeof(*elf));
283 }
284
285 marks[MARK_START] = LOADADDR(minp);
286 marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
287 marks[MARK_VENTRY] = elf->e_entry;
288 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */
289 marks[MARK_SYM] = LOADADDR(elfp);
290 marks[MARK_END] = LOADADDR(maxp);
291
292 return 0;
293 }
294