Annotation of sys/lib/libsa/loadfile.c, Revision 1.1.1.1
1.1 nbrk 1: /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
2: /* $OpenBSD: loadfile.c,v 1.14 2007/06/26 10:32:50 tom 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: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the NetBSD
23: * Foundation, Inc. and its contributors.
24: * 4. Neither the name of The NetBSD Foundation nor the names of its
25: * contributors may be used to endorse or promote products derived
26: * from this software without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38: * POSSIBILITY OF SUCH DAMAGE.
39: */
40:
41: /*
42: * Copyright (c) 1992, 1993
43: * The Regents of the University of California. All rights reserved.
44: *
45: * This code is derived from software contributed to Berkeley by
46: * Ralph Campbell.
47: *
48: * Redistribution and use in source and binary forms, with or without
49: * modification, are permitted provided that the following conditions
50: * are met:
51: * 1. Redistributions of source code must retain the above copyright
52: * notice, this list of conditions and the following disclaimer.
53: * 2. Redistributions in binary form must reproduce the above copyright
54: * notice, this list of conditions and the following disclaimer in the
55: * documentation and/or other materials provided with the distribution.
56: * 3. Neither the name of the University nor the names of its contributors
57: * may be used to endorse or promote products derived from this software
58: * without specific prior written permission.
59: *
60: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70: * SUCH DAMAGE.
71: *
72: * @(#)boot.c 8.1 (Berkeley) 6/10/93
73: */
74:
75: #ifdef _STANDALONE
76: #include <lib/libkern/libkern.h>
77: #include <lib/libsa/stand.h>
78: #else
79: #include <stdio.h>
80: #include <string.h>
81: #include <errno.h>
82: #include <stdlib.h>
83: #include <unistd.h>
84: #include <fcntl.h>
85: #include <err.h>
86: #endif
87:
88: #include <sys/param.h>
89: #include <sys/exec.h>
90:
91: #include "loadfile.h"
92:
93: #ifdef BOOT_ECOFF
94: #include <sys/exec_ecoff.h>
95: static int coff_exec(int, struct ecoff_exechdr *, u_long *, int);
96: #endif
97: #ifdef BOOT_AOUT
98: #include <sys/exec_aout.h>
99: static int aout_exec(int, struct exec *, u_long *, int);
100: #endif
101:
102: #ifdef BOOT_ELF
103: #include <sys/exec_elf.h>
104: #if defined(BOOT_ELF32) && defined(BOOT_ELF64)
105: /*
106: * Both defined, so elf32_exec() and elf64_exec() need to be separately
107: * created (can't do it by including loadfile_elf.c here).
108: */
109: int elf32_exec(int, Elf32_Ehdr *, u_long *, int);
110: int elf64_exec(int, Elf64_Ehdr *, u_long *, int);
111: #else
112: #include "loadfile_elf.c"
113: #endif
114: #endif
115:
116: /*
117: * Open 'filename', read in program and return -1 on error otherwise fd,
118: * with file still open.
119: * Also fills in marks.
120: */
121: int
122: loadfile(const char *fname, u_long *marks, int flags)
123: {
124: union {
125: #ifdef BOOT_ECOFF
126: struct ecoff_exechdr coff;
127: #endif
128: #if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32)
129: Elf32_Ehdr elf32;
130: #endif
131: #if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64)
132: Elf64_Ehdr elf64;
133: #endif
134: #ifdef BOOT_AOUT
135: struct exec aout;
136: #endif
137:
138: } hdr;
139: ssize_t nr;
140: int fd, rval;
141:
142: /* Open the file. */
143: if ((fd = open(fname, 0)) < 0) {
144: WARN(("open %s", fname ? fname : "<default>"));
145: return -1;
146: }
147:
148: /* Read the exec header. */
149: if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
150: WARN(("read header"));
151: goto err;
152: }
153:
154: #ifdef BOOT_ECOFF
155: if (!ECOFF_BADMAG(&hdr.coff)) {
156: rval = coff_exec(fd, &hdr.coff, marks, flags);
157: } else
158: #endif
159: #if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32)
160: if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
161: hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
162: rval = elf32_exec(fd, &hdr.elf32, marks, flags);
163: } else
164: #endif
165: #if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64)
166: if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
167: hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
168: rval = elf64_exec(fd, &hdr.elf64, marks, flags);
169: } else
170: #endif
171: #ifdef BOOT_AOUT
172: if (OKMAGIC(N_GETMAGIC(hdr.aout))
173: #ifndef NO_MID_CHECK
174: && N_GETMID(hdr.aout) == MID_MACHINE
175: #endif
176: ) {
177: rval = aout_exec(fd, &hdr.aout, marks, flags);
178: } else
179: #endif
180: {
181: rval = 1;
182: errno = EFTYPE;
183: WARN(("%s", fname ? fname : "<default>"));
184: }
185:
186: if (rval == 0) {
187: PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START]));
188: return fd;
189: }
190: err:
191: (void)close(fd);
192: return -1;
193: }
194:
195: #ifdef BOOT_ECOFF
196: static int
197: coff_exec(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags)
198: {
199: paddr_t offset = marks[MARK_START];
200: paddr_t minp = ~0, maxp = 0, pos;
201:
202: /* Read in text. */
203: if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1) {
204: WARN(("lseek text"));
205: return 1;
206: }
207:
208: if (coff->a.tsize != 0) {
209: if (flags & LOAD_TEXT) {
210: PROGRESS(("%lu", coff->a.tsize));
211: if (READ(fd, coff->a.text_start, coff->a.tsize) !=
212: coff->a.tsize) {
213: return 1;
214: }
215: }
216: else {
217: if (lseek(fd, coff->a.tsize, SEEK_CUR) == -1) {
218: WARN(("read text"));
219: return 1;
220: }
221: }
222: if (flags & (COUNT_TEXT|LOAD_TEXT)) {
223: pos = coff->a.text_start;
224: if (minp > pos)
225: minp = pos;
226: pos += coff->a.tsize;
227: if (maxp < pos)
228: maxp = pos;
229: }
230: }
231:
232: /* Read in data. */
233: if (coff->a.dsize != 0) {
234: if (flags & LOAD_DATA) {
235: PROGRESS(("+%lu", coff->a.dsize));
236: if (READ(fd, coff->a.data_start, coff->a.dsize) !=
237: coff->a.dsize) {
238: WARN(("read data"));
239: return 1;
240: }
241: }
242: if (flags & (COUNT_DATA|LOAD_DATA)) {
243: pos = coff->a.data_start;
244: if (minp > pos)
245: minp = pos;
246: pos += coff->a.dsize;
247: if (maxp < pos)
248: maxp = pos;
249: }
250: }
251:
252: /* Zero out bss. */
253: if (coff->a.bsize != 0) {
254: if (flags & LOAD_BSS) {
255: PROGRESS(("+%lu", coff->a.bsize));
256: BZERO(coff->a.bss_start, coff->a.bsize);
257: }
258: if (flags & (COUNT_BSS|LOAD_BSS)) {
259: pos = coff->a.bss_start;
260: if (minp > pos)
261: minp = pos;
262: pos = coff->a.bsize;
263: if (maxp < pos)
264: maxp = pos;
265: }
266: }
267:
268: marks[MARK_START] = LOADADDR(minp);
269: marks[MARK_ENTRY] = LOADADDR(coff->a.entry);
270: marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */
271: marks[MARK_SYM] = LOADADDR(maxp);
272: marks[MARK_END] = LOADADDR(maxp);
273: return 0;
274: }
275: #endif /* BOOT_ECOFF */
276:
277: #ifdef BOOT_AOUT
278: static int
279: aout_exec(int fd, struct exec *x, u_long *marks, int flags)
280: {
281: u_long entry = x->a_entry;
282: paddr_t aoutp = 0;
283: paddr_t minp, maxp;
284: int cc;
285: paddr_t offset = marks[MARK_START];
286: u_long magic = N_GETMAGIC(*x);
287: int sub;
288:
289: /* In OMAGIC and NMAGIC, exec header isn't part of text segment */
290: if (magic == OMAGIC || magic == NMAGIC)
291: sub = 0;
292: else
293: sub = sizeof(*x);
294:
295: minp = maxp = ALIGNENTRY(entry);
296:
297: if (lseek(fd, sizeof(*x), SEEK_SET) == -1) {
298: WARN(("lseek text"));
299: return 1;
300: }
301:
302: /*
303: * Leave a copy of the exec header before the text.
304: * The kernel may use this to verify that the
305: * symbols were loaded by this boot program.
306: */
307: if (magic == OMAGIC || magic == NMAGIC) {
308: if (flags & LOAD_HDR && maxp >= sizeof(*x))
309: BCOPY(x, maxp - sizeof(*x), sizeof(*x));
310: }
311: else {
312: if (flags & LOAD_HDR)
313: BCOPY(x, maxp, sizeof(*x));
314: if (flags & (LOAD_HDR|COUNT_HDR))
315: maxp += sizeof(*x);
316: }
317:
318: /*
319: * Read in the text segment.
320: */
321: if (flags & LOAD_TEXT) {
322: PROGRESS(("%ld", x->a_text));
323:
324: if (READ(fd, maxp, x->a_text - sub) != x->a_text - sub) {
325: WARN(("read text"));
326: return 1;
327: }
328: } else {
329: if (lseek(fd, x->a_text - sub, SEEK_CUR) == -1) {
330: WARN(("seek text"));
331: return 1;
332: }
333: }
334: if (flags & (LOAD_TEXT|COUNT_TEXT))
335: maxp += x->a_text - sub;
336:
337: /*
338: * Provide alignment if required
339: */
340: if (magic == ZMAGIC || magic == NMAGIC) {
341: int size = -(unsigned int)maxp & (__LDPGSZ - 1);
342:
343: if (flags & LOAD_TEXTA) {
344: PROGRESS(("/%d", size));
345: BZERO(maxp, size);
346: }
347:
348: if (flags & (LOAD_TEXTA|COUNT_TEXTA))
349: maxp += size;
350: }
351:
352: /*
353: * Read in the data segment.
354: */
355: if (flags & LOAD_DATA) {
356: PROGRESS(("+%ld", x->a_data));
357:
358: if (READ(fd, maxp, x->a_data) != x->a_data) {
359: WARN(("read data"));
360: return 1;
361: }
362: }
363: else {
364: if (lseek(fd, x->a_data, SEEK_CUR) == -1) {
365: WARN(("seek data"));
366: return 1;
367: }
368: }
369: if (flags & (LOAD_DATA|COUNT_DATA))
370: maxp += x->a_data;
371:
372: /*
373: * Zero out the BSS section.
374: * (Kernel doesn't care, but do it anyway.)
375: */
376: if (flags & LOAD_BSS) {
377: PROGRESS(("+%ld", x->a_bss));
378:
379: BZERO(maxp, x->a_bss);
380: }
381:
382: if (flags & (LOAD_BSS|COUNT_BSS))
383: maxp += x->a_bss;
384:
385: /*
386: * Read in the symbol table and strings.
387: * (Always set the symtab size word.)
388: */
389: if (flags & LOAD_SYM)
390: BCOPY(&x->a_syms, maxp, sizeof(x->a_syms));
391:
392: if (flags & (LOAD_SYM|COUNT_SYM)) {
393: maxp += sizeof(x->a_syms);
394: aoutp = maxp;
395: }
396:
397: if (x->a_syms > 0) {
398: /* Symbol table and string table length word. */
399:
400: if (flags & LOAD_SYM) {
401: PROGRESS(("+[%ld", x->a_syms));
402:
403: if (READ(fd, maxp, x->a_syms) != x->a_syms) {
404: WARN(("read symbols"));
405: return 1;
406: }
407: } else {
408: if (lseek(fd, x->a_syms, SEEK_CUR) == -1) {
409: WARN(("seek symbols"));
410: return 1;
411: }
412: }
413: if (flags & (LOAD_SYM|COUNT_SYM))
414: maxp += x->a_syms;
415:
416: if (read(fd, &cc, sizeof(cc)) != sizeof(cc)) {
417: WARN(("read string table"));
418: return 1;
419: }
420:
421: if (flags & LOAD_SYM) {
422: BCOPY(&cc, maxp, sizeof(cc));
423:
424: /* String table. Length word includes itself. */
425:
426: PROGRESS(("+%d]", cc));
427: }
428: if (flags & (LOAD_SYM|COUNT_SYM))
429: maxp += sizeof(cc);
430:
431: cc -= sizeof(int);
432: if (cc <= 0) {
433: WARN(("symbol table too short"));
434: return 1;
435: }
436:
437: if (flags & LOAD_SYM) {
438: if (READ(fd, maxp, cc) != cc) {
439: WARN(("read strings"));
440: return 1;
441: }
442: } else {
443: if (lseek(fd, cc, SEEK_CUR) == -1) {
444: WARN(("seek strings"));
445: return 1;
446: }
447: }
448: if (flags & (LOAD_SYM|COUNT_SYM))
449: maxp += cc;
450: }
451:
452: marks[MARK_START] = LOADADDR(minp);
453: marks[MARK_ENTRY] = LOADADDR(entry);
454: marks[MARK_NSYM] = x->a_syms;
455: marks[MARK_SYM] = LOADADDR(aoutp);
456: marks[MARK_END] = LOADADDR(maxp);
457: return 0;
458: }
459: #endif /* BOOT_AOUT */
CVSweb