Annotation of qemu/roms/SLOF/lib/libelf/elf.c, revision 1.1.1.2

1.1       root        1: /******************************************************************************
1.1.1.2 ! root        2:  * Copyright (c) 2004, 2011 IBM Corporation
1.1       root        3:  * All rights reserved.
                      4:  * This program and the accompanying materials
                      5:  * are made available under the terms of the BSD License
                      6:  * which accompanies this distribution, and is available at
                      7:  * http://www.opensource.org/licenses/bsd-license.php
                      8:  *
                      9:  * Contributors:
                     10:  *     IBM Corporation - initial implementation
                     11:  *****************************************************************************/
                     12: 
1.1.1.2 ! root       13: /*
        !            14:  * ELF loader
        !            15:  */
1.1       root       16: 
                     17: #include <string.h>
1.1.1.2 ! root       18: #include <cache.h>
1.1       root       19: #include <libelf.h>
1.1.1.2 ! root       20: #include <byteorder.h>
1.1       root       21: 
                     22: /**
                     23:  * elf_check_file tests if the file at file_addr is
                     24:  * a correct endian, ELF PPC executable
                     25:  * @param file_addr  pointer to the start of the ELF file
                     26:  * @return           the class (1 for 32 bit, 2 for 64 bit)
                     27:  *                   -1 if it is not an ELF file
                     28:  *                   -2 if it has the wrong endianess
                     29:  *                   -3 if it is not an ELF executable
                     30:  *                   -4 if it is not for PPC
                     31:  */
                     32: static int
                     33: elf_check_file(unsigned long *file_addr)
                     34: {
                     35:        struct ehdr *ehdr = (struct ehdr *) file_addr;
                     36:        /* check if it is an ELF image at all */
                     37:        if (cpu_to_be32(ehdr->ei_ident) != 0x7f454c46)
                     38:                return -1;
                     39: 
                     40:        /* endian check */
1.1.1.2 ! root       41: #ifdef __BIG_ENDIAN__
1.1       root       42:        if (ehdr->ei_data != 2)
                     43:                /* not a big endian image */
                     44: #else
                     45:        if (ehdr->ei_data == 2)
                     46:                /* not a little endian image */
                     47: #endif
                     48:                return -2;
                     49: 
1.1.1.2 ! root       50:        /* check if it is an ELF executable ... and also
        !            51:         * allow DYN files, since this is specified by ePAPR */
        !            52:        if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1.1       root       53:                return -3;
                     54: 
                     55:        /* check if it is a PPC ELF executable */
                     56:        if (ehdr->e_machine != 0x14 && ehdr->e_machine != 0x15)
                     57:                return -4;
                     58: 
                     59:        return ehdr->ei_class;
                     60: }
                     61: 
                     62: /**
                     63:  * load_elf_file tries to load the ELF file specified in file_addr
                     64:  *
                     65:  * it first checks if the file is a PPC ELF executable and then loads
                     66:  * the segments depending if it is a 64bit or 32 bit ELF file
                     67:  *
                     68:  * @param file_addr  pointer to the start of the elf file
                     69:  * @param entry      pointer where the ELF loader will store
                     70:  *                   the entry point
1.1.1.2 ! root       71:  * @param pre_load   handler that is called before copying a segment
        !            72:  * @param post_load  handler that is called after copying a segment
1.1       root       73:  * @return           1 for a 32 bit file
                     74:  *                   2 for a 64 bit file
                     75:  *                   anything else means an error during load
                     76:  */
                     77: int
1.1.1.2 ! root       78: elf_load_file(void *file_addr, unsigned long *entry,
        !            79:               int (*pre_load)(void*, long),
        !            80:               void (*post_load)(void*, long))
1.1       root       81: {
                     82:        int type = elf_check_file(file_addr);
1.1.1.2 ! root       83: 
        !            84:        switch (type) {
        !            85:        case 1:
        !            86:                *entry = elf_load_segments32(file_addr, 0, pre_load, post_load);
        !            87:                break;
        !            88:        case 2:
        !            89:                *entry = elf_load_segments64(file_addr, 0, pre_load, post_load);
        !            90:                break;
        !            91:        }
        !            92: 
        !            93:        return type;
        !            94: }
        !            95: 
        !            96: 
        !            97: /**
        !            98:  * load_elf_file_to_addr loads an ELF file to given address.
        !            99:  * This is useful for 64-bit vmlinux images that use the virtual entry
        !           100:  * point address in their headers, and thereby need a special treatment.
        !           101:  *
        !           102:  * @param file_addr  pointer to the start of the elf file
        !           103:  * @param entry      pointer where the ELF loader will store
        !           104:  *                   the entry point
        !           105:  * @param pre_load   handler that is called before copying a segment
        !           106:  * @param post_load  handler that is called after copying a segment
        !           107:  * @return           1 for a 32 bit file
        !           108:  *                   2 for a 64 bit file
        !           109:  *                   anything else means an error during load
        !           110:  */
        !           111: int
        !           112: elf_load_file_to_addr(void *file_addr, void *addr, unsigned long *entry,
        !           113:                       int (*pre_load)(void*, long),
        !           114:                       void (*post_load)(void*, long))
        !           115: {
        !           116:        int type;
        !           117:        long offset;
        !           118: 
        !           119:        type = elf_check_file(file_addr);
        !           120: 
1.1       root      121:        switch (type) {
                    122:        case 1:
1.1.1.2 ! root      123:                /* Parse 32-bit image */
        !           124:                offset = (long)addr - elf_get_base_addr32(file_addr);
        !           125:                *entry = elf_load_segments32(file_addr, offset, pre_load,
        !           126:                                             post_load) + offset;
        !           127:                // TODO: elf_relocate32(...)
1.1       root      128:                break;
                    129:        case 2:
1.1.1.2 ! root      130:                /* Parse 64-bit image */
        !           131:                offset = (long)addr - elf_get_base_addr64(file_addr);
        !           132:                *entry = elf_load_segments64(file_addr, offset, pre_load,
        !           133:                                             post_load) + offset;
        !           134:                elf_relocate64(file_addr, offset);
1.1       root      135:                break;
                    136:        }
1.1.1.2 ! root      137: 
1.1       root      138:        return type;
                    139: }
1.1.1.2 ! root      140: 
        !           141: 
        !           142: /**
        !           143:  * Get the base load address of the ELF image
        !           144:  * @return  The base address or -1 for error
        !           145:  */
        !           146: long
        !           147: elf_get_base_addr(void *file_addr)
        !           148: {
        !           149:        int type;
        !           150: 
        !           151:        type = elf_check_file(file_addr);
        !           152: 
        !           153:        switch (type) {
        !           154:        case 1:
        !           155:                /* Return 32-bit image base address */
        !           156:                return elf_get_base_addr32(file_addr);
        !           157:                break;
        !           158:        case 2:
        !           159:                /* Return 64-bit image base address */
        !           160:                return elf_get_base_addr64(file_addr);
        !           161:                break;
        !           162:        }
        !           163: 
        !           164:        return -1;
        !           165: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.