[BACK]Return to elf.c CVS log [TXT][DIR] Up to [local] / prex-old / boot / common

Annotation of prex-old/boot/common/elf.c, Revision 1.1.1.1

1.1       nbrk        1: /*-
                      2:  * Copyright (c) 2005-2006, Kohsuke Ohtani
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the author nor the names of any co-contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
                     30: /*
                     31:  * elf.c - ELF file format support
                     32:  */
                     33:
                     34: #include <boot.h>
                     35: #include <prex/bootinfo.h>
                     36: #include <sys/elf.h>
                     37: #include <platform.h>
                     38:
                     39: extern int nr_img;             /* number of images */
                     40:
                     41: #define SHF_VALID      (SHF_ALLOC | SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE)
                     42:
                     43: static char *sect_addr[32];    /* array of section address */
                     44:
                     45: static int
                     46: load_executable(char *img, struct module *m)
                     47: {
                     48:        Elf32_Ehdr *ehdr;
                     49:        Elf32_Phdr *phdr;
                     50:        u_long phys_base;
                     51:        int i;
                     52:
                     53:        phys_base = load_base;
                     54:        ehdr = (Elf32_Ehdr *)img;
                     55:        phdr = (Elf32_Phdr *)((u_long)ehdr + ehdr->e_phoff);
                     56:        m->phys = load_base;
                     57:        phys_base = load_base;
                     58:        elf_print("phys addr=%x\n", phys_base);
                     59:
                     60:        for (i = 0; i < (int)ehdr->e_phnum; i++, phdr++) {
                     61:                if (phdr->p_type != PT_LOAD)
                     62:                        continue;
                     63:
                     64:                elf_print("p_flags=%x\n", (int)phdr->p_flags);
                     65:                elf_print("p_align=%x\n", (int)phdr->p_align);
                     66:                elf_print("p_paddr=%x\n", (int)phdr->p_paddr);
                     67:
                     68:                if (i >= 2) {
                     69:                        elf_print("skipping extra phdr\n");
                     70:                        continue;
                     71:                }
                     72:                if (phdr->p_flags & PF_X) {
                     73:                        /* Text */
                     74:                        m->text = phdr->p_vaddr;
                     75:                        m->textsz = (size_t)phdr->p_memsz;
                     76:                } else {
                     77:                        /* Data & BSS */
                     78:                        m->data = phdr->p_vaddr;
                     79:                        m->datasz = (size_t)phdr->p_filesz;
                     80:                        m->bsssz =
                     81:                                (size_t)(phdr->p_memsz - phdr->p_filesz);
                     82:                        load_base = phys_base + (m->data - m->text);
                     83:                }
                     84:                if (phdr->p_filesz > 0) {
                     85:                        memcpy((char *)load_base, img + phdr->p_offset,
                     86:                               (size_t)phdr->p_filesz);
                     87:                        elf_print("load: offset=%x size=%x\n",
                     88:                                load_base, (int)phdr->p_filesz);
                     89:                }
                     90:                if (!(phdr->p_flags & PF_X)) {
                     91:                        if (m->bsssz > 0) {
                     92:                                /* Zero fill BSS */
                     93:                                memset((char *)load_base + m->datasz,
                     94:                                       0, m->bsssz);
                     95:                        }
                     96:                        load_base += phdr->p_memsz;
                     97:                }
                     98:        }
                     99:        /* workaround for data/bss size is 0 */
                    100:        if (m->data == 0)
                    101:                load_base = phys_base + m->textsz;
                    102:
                    103:        load_base = PAGE_ALIGN(load_base);
                    104:        m->size = (size_t)(load_base - m->phys);
                    105:        m->entry = ehdr->e_entry;
                    106:        elf_print("module size=%x entry=%x\n", m->size, m->entry);
                    107:        return 0;
                    108: }
                    109:
                    110: static int
                    111: relocate_section_rela(Elf32_Sym *sym_table, Elf32_Rela *rela,
                    112:                      char *target_sect, int nr_reloc)
                    113: {
                    114:        Elf32_Sym *sym;
                    115:        Elf32_Addr sym_val;
                    116:        int i;
                    117:
                    118:        for (i = 0; i < nr_reloc; i++) {
                    119:                sym = &sym_table[ELF32_R_SYM(rela->r_info)];
                    120:                if (sym->st_shndx != STN_UNDEF) {
                    121:                        sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
                    122:                                + sym->st_value;
                    123:                        if (relocate_rela(rela, sym_val, target_sect) != 0)
                    124:                                return -1;
                    125:                } else if (ELF32_ST_BIND(sym->st_info) != STB_WEAK) {
                    126:                        printk("Undefined symbol for rela[%x] sym=%x\n",
                    127:                               i, sym);
                    128:                        return -1;
                    129:                } else {
                    130:                        elf_print("Undefined weak symbol for rela[%x]\n", i);
                    131:                }
                    132:                rela++;
                    133:        }
                    134:        return 0;
                    135: }
                    136:
                    137: static int
                    138: relocate_section_rel(Elf32_Sym *sym_table, Elf32_Rel *rel,
                    139:                     char *target_sect, int nr_reloc)
                    140: {
                    141:        Elf32_Sym *sym;
                    142:        Elf32_Addr sym_val;
                    143:        int i;
                    144:
                    145:        for (i = 0; i < nr_reloc; i++) {
                    146:                sym = &sym_table[ELF32_R_SYM(rel->r_info)];
                    147:                if (sym->st_shndx != STN_UNDEF) {
                    148:                        sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
                    149:                                + sym->st_value;
                    150:                        if (relocate_rel(rel, sym_val, target_sect) != 0)
                    151:                                return -1;
                    152:                } else if (ELF32_ST_BIND(sym->st_info) != STB_WEAK) {
                    153:                        printk("Undefined symbol for rel[%x] sym=%x\n",
                    154:                               i, sym);
                    155:                        return -1;
                    156:                } else {
                    157:                        elf_print("Undefined weak symbol for rel[%x]\n", i);
                    158:                }
                    159:                rel++;
                    160:        }
                    161:        return 0;
                    162: }
                    163:
                    164: static int
                    165: relocate_section(char *img, Elf32_Shdr *shdr)
                    166: {
                    167:        Elf32_Sym *sym_table;
                    168:        char *target_sect;
                    169:        int nr_reloc, err;
                    170:
                    171:        if (shdr->sh_entsize == 0)
                    172:                return 0;
                    173:        if ((target_sect = sect_addr[shdr->sh_info]) == 0)
                    174:                return -1;
                    175:        if ((sym_table = (Elf32_Sym *)sect_addr[shdr->sh_link]) == 0)
                    176:                return -1;
                    177:
                    178:        nr_reloc = (int)(shdr->sh_size / shdr->sh_entsize);
                    179:        switch (shdr->sh_type) {
                    180:        case SHT_REL:
                    181:                err = relocate_section_rel(sym_table,
                    182:                                (Elf32_Rel *)(img + shdr->sh_offset),
                    183:                                target_sect, nr_reloc);
                    184:                break;
                    185:
                    186:        case SHT_RELA:
                    187:                err = relocate_section_rela(sym_table,
                    188:                                (Elf32_Rela *)(img + shdr->sh_offset),
                    189:                                target_sect, nr_reloc);
                    190:                break;
                    191:
                    192:        default:
                    193:                err = -1;
                    194:                break;
                    195:        }
                    196:        return err;
                    197: }
                    198:
                    199: static int
                    200: load_relocatable(char *img, struct module *m)
                    201: {
                    202:        Elf32_Ehdr *ehdr;
                    203:        Elf32_Shdr *shdr;
                    204:        u_long sect_base, bss_base;
                    205:        int i;
                    206:
                    207:        ehdr = (Elf32_Ehdr *)img;
                    208:        shdr = (Elf32_Shdr *)((u_long)ehdr + ehdr->e_shoff);
                    209:        bss_base = 0;
                    210:        m->phys = load_base;
                    211:        elf_print("phys addr=%x\n", load_base);
                    212:
                    213:        /* Copy sections */
                    214:        for (i = 0; i < (int)ehdr->e_shnum; i++, shdr++) {
                    215:                sect_addr[i] = 0;
                    216:                if (shdr->sh_type == SHT_PROGBITS) {
                    217:
                    218:                        elf_print("sh_addr=%x\n", shdr->sh_addr);
                    219:                        elf_print("sh_size=%x\n", shdr->sh_size);
                    220:                        elf_print("sh_offset=%x\n", shdr->sh_offset);
                    221:                        elf_print("sh_flags=%x\n", shdr->sh_flags);
                    222:
                    223:                        switch (shdr->sh_flags & SHF_VALID) {
                    224:                        case (SHF_ALLOC | SHF_EXECINSTR):
                    225:                                /* Text */
                    226:                                m->text = (u_long)phys_to_virt(load_base);
                    227:                                break;
                    228:                        case (SHF_ALLOC | SHF_WRITE):
                    229:                                /* Data */
                    230:                                if (m->data == 0)
                    231:                                        m->data =
                    232:                                                (u_long)phys_to_virt(load_base + shdr->sh_addr);
                    233:                                break;
                    234:                        case SHF_ALLOC:
                    235:                                /* rodata */
                    236:                                /* Note: rodata is treated as text. */
                    237:                                break;
                    238:                        default:
                    239:                                continue;
                    240:                        }
                    241:                        sect_base = load_base + shdr->sh_addr;
                    242:                        memcpy((char *)sect_base, img + shdr->sh_offset,
                    243:                               (size_t)shdr->sh_size);
                    244:                        elf_print("load: offset=%x size=%x\n",
                    245:                                sect_base, (int)shdr->sh_size);
                    246:
                    247:                        sect_addr[i] = (char *)sect_base;
                    248:                } else if (shdr->sh_type == SHT_NOBITS) {
                    249:                        /* BSS */
                    250:                        m->bsssz = (size_t)shdr->sh_size;
                    251:                        sect_base = load_base + shdr->sh_addr;
                    252:                        bss_base = sect_base;
                    253:
                    254:                        /* Zero fill BSS */
                    255:                        memset((char *)sect_base, 0, (size_t)shdr->sh_size);
                    256:
                    257:                        sect_addr[i] = (char *)sect_base;
                    258:                } else if (shdr->sh_type == SHT_SYMTAB) {
                    259:                        /* Symbol table */
                    260:                        sect_addr[i] = img + shdr->sh_offset;
                    261:                }
                    262:        }
                    263:        m->textsz = (size_t)(m->data - m->text);
                    264:        m->datasz = (size_t)(bss_base - m->data);
                    265:
                    266:        load_base = bss_base + m->bsssz;
                    267:        load_base = PAGE_ALIGN(load_base);
                    268:
                    269:        elf_print("module load_base=%x text=%x\n", load_base, m->text);
                    270:        m->size = (size_t)(load_base - (u_long)virt_to_phys(m->text));
                    271:        m->entry = (u_long)phys_to_virt(ehdr->e_entry + m->phys);
                    272:        elf_print("module size=%x entry=%x\n", m->size, m->entry);
                    273:
                    274:        /* Process relocation */
                    275:        shdr = (Elf32_Shdr *)((u_long)ehdr + ehdr->e_shoff);
                    276:        for (i = 0; i < (int)ehdr->e_shnum; i++, shdr++) {
                    277:                if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
                    278:                        if (relocate_section(img, shdr) != 0)
                    279:                                return -1;
                    280:                }
                    281:        }
                    282:        return 0;
                    283: }
                    284:
                    285: /*
                    286:  * Load the program from specified ELF image data stored in memory.
                    287:  * The boot information is filled after loading the program.
                    288:  */
                    289: int
                    290: elf_load(char *img, struct module *m)
                    291: {
                    292:        Elf32_Ehdr *ehdr;
                    293:        Elf32_Phdr *phdr;
                    294:
                    295:        elf_print("\nelf_load\n");
                    296:
                    297:        ehdr = (Elf32_Ehdr *)img;
                    298:
                    299:        /*  Check ELF header */
                    300:        if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
                    301:            (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
                    302:            (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
                    303:            (ehdr->e_ident[EI_MAG3] != ELFMAG3))
                    304:                return -1;
                    305:
                    306:        phdr = (Elf32_Phdr *)((u_long)ehdr + ehdr->e_ehsize);
                    307:
                    308:        if (nr_img == 0) {
                    309:                /*  Initialize the load address */
                    310:                load_base = (u_long)phys_to_virt(phdr->p_paddr);
                    311:                if (load_base == 0)
                    312:                        return -1;
                    313:                elf_print("kernel base=%x\n", load_base);
                    314:                load_start = load_base;
                    315:        }
                    316:        else if (nr_img == 1) {
                    317:                /*  Second image => Driver */
                    318:                elf_print("driver base=%x\n", load_base);
                    319:        }
                    320:        else {
                    321:                /* Other images => Boot tasks */
                    322:                elf_print("task base=%x\n", load_base);
                    323:        }
                    324:
                    325:        switch (ehdr->e_type) {
                    326:        case ET_EXEC:
                    327:                if (load_executable(img, m) != 0)
                    328:                        return -1;
                    329:                break;
                    330:        case ET_REL:
                    331:                if (load_relocatable(img, m) != 0)
                    332:                        return -1;
                    333:                break;
                    334:        default:
                    335:                elf_print("Unsupported file type\n");
                    336:                return -1;
                    337:        }
                    338:        nr_img++;
                    339:        return 0;
                    340: }

CVSweb