Annotation of qemu/roms/SLOF/lib/libelf/elf32.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 2004, 2011 IBM Corporation
        !             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: 
        !            13: /*
        !            14:  * 32-bit ELF loader
        !            15:  */
        !            16:  
        !            17: #include <string.h>
        !            18: #include <libelf.h>
        !            19: 
        !            20: struct ehdr32 {
        !            21:        uint32_t ei_ident;
        !            22:        uint8_t ei_class;
        !            23:        uint8_t ei_data;
        !            24:        uint8_t ei_version;
        !            25:        uint8_t ei_pad[9];
        !            26:        uint16_t e_type;
        !            27:        uint16_t e_machine;
        !            28:        uint32_t e_version;
        !            29:        uint32_t e_entry;
        !            30:        uint32_t e_phoff;
        !            31:        uint32_t e_shoff;
        !            32:        uint32_t e_flags;
        !            33:        uint16_t e_ehsize;
        !            34:        uint16_t e_phentsize;
        !            35:        uint16_t e_phnum;
        !            36:        uint16_t e_shentsize;
        !            37:        uint16_t e_shnum;
        !            38:        uint16_t e_shstrndx;
        !            39: };
        !            40: 
        !            41: struct phdr32 {
        !            42:        uint32_t p_type;
        !            43:        uint32_t p_offset;
        !            44:        uint32_t p_vaddr;
        !            45:        uint32_t p_paddr;
        !            46:        uint32_t p_filesz;
        !            47:        uint32_t p_memsz;
        !            48:        uint32_t p_flags;
        !            49:        uint32_t p_align;
        !            50: };
        !            51: 
        !            52: 
        !            53: static struct phdr32*
        !            54: get_phdr32(void *file_addr)
        !            55: {
        !            56:        return (struct phdr32 *) (((unsigned char *)file_addr)
        !            57:                + ((struct ehdr32 *)file_addr)->e_phoff);
        !            58: }
        !            59: 
        !            60: static void
        !            61: load_segment(void *file_addr, struct phdr32 *phdr, signed long offset,
        !            62:              int (*pre_load)(void*, long),
        !            63:              void (*post_load)(void*, long))
        !            64: {
        !            65:        unsigned long src = phdr->p_offset + (unsigned long) file_addr;
        !            66:        unsigned long destaddr;
        !            67: 
        !            68:        destaddr = (unsigned long)phdr->p_paddr;
        !            69:        destaddr = destaddr + offset;
        !            70: 
        !            71:        /* check if we're allowed to copy */
        !            72:        if (pre_load != NULL) {
        !            73:                if (pre_load((void*)destaddr, phdr->p_memsz) != 0)
        !            74:                        return;
        !            75:        }
        !            76: 
        !            77:        /* copy into storage */
        !            78:        memmove((void *)destaddr, (void *)src, phdr->p_filesz);
        !            79: 
        !            80:        /* clear bss */
        !            81:        memset((void *)(destaddr + phdr->p_filesz), 0,
        !            82:               phdr->p_memsz - phdr->p_filesz);
        !            83: 
        !            84:        if (phdr->p_memsz && post_load) {
        !            85:                post_load((void*)destaddr, phdr->p_memsz);
        !            86:        }
        !            87: }
        !            88: 
        !            89: unsigned int
        !            90: elf_load_segments32(void *file_addr, signed long offset,
        !            91:                     int (*pre_load)(void*, long),
        !            92:                     void (*post_load)(void*, long))
        !            93: {
        !            94:        struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
        !            95:        /* Calculate program header address */
        !            96:        struct phdr32 *phdr = get_phdr32(file_addr);
        !            97:        int i;
        !            98:        signed int virt2phys = 0;       /* Offset between virtual and physical */
        !            99: 
        !           100:        /* loop e_phnum times */
        !           101:        for (i = 0; i <= ehdr->e_phnum; i++) {
        !           102:                /* PT_LOAD ? */
        !           103:                if (phdr->p_type == 1) {
        !           104:                        if (!virt2phys) {
        !           105:                                virt2phys = phdr->p_paddr - phdr->p_vaddr;
        !           106:                        }
        !           107:                        /* copy segment */
        !           108:                        load_segment(file_addr, phdr, offset, pre_load,
        !           109:                                     post_load);
        !           110:                }
        !           111:                /* step to next header */
        !           112:                phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
        !           113:        }
        !           114: 
        !           115:        /* Entry point is always a virtual address, so translate it
        !           116:         * to physical before returning it */
        !           117:        return ehdr->e_entry + virt2phys;
        !           118: }
        !           119: 
        !           120: /**
        !           121:  * Return the base address for loading (i.e. the address of the first PT_LOAD
        !           122:  * segment)
        !           123:  * @param  file_addr   pointer to the ELF file in memory
        !           124:  * @return             the base address
        !           125:  */
        !           126: long
        !           127: elf_get_base_addr32(void *file_addr)
        !           128: {
        !           129:        struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
        !           130:        struct phdr32 *phdr = get_phdr32(file_addr);
        !           131:        int i;
        !           132: 
        !           133:        /* loop e_phnum times */
        !           134:        for (i = 0; i <= ehdr->e_phnum; i++) {
        !           135:                /* PT_LOAD ? */
        !           136:                if (phdr->p_type == 1) {
        !           137:                        return phdr->p_paddr;
        !           138:                }
        !           139:                /* step to next header */
        !           140:                phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
        !           141:        }
        !           142: 
        !           143:        return 0;
        !           144: }

unix.superglobalmegacorp.com

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