[BACK]Return to loadfile.c CVS log [TXT][DIR] Up to [local] / sys / lib / libsa

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