Annotation of qemu/roms/SLOF/lib/libelf/elf32.c, revision 1.1.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.