Home | History | Annotate | Line # | Download | only in hpcboot
load_elf.cpp revision 1.1.4.2
      1  1.1.4.2  nathanw /*	$NetBSD: load_elf.cpp,v 1.1.4.2 2001/06/21 19:22:46 nathanw Exp $	*/
      2      1.1      uch 
      3      1.1      uch /*-
      4      1.1      uch  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5      1.1      uch  * All rights reserved.
      6      1.1      uch  *
      7      1.1      uch  * This code is derived from software contributed to The NetBSD Foundation
      8      1.1      uch  * by UCHIYAMA Yasushi.
      9      1.1      uch  *
     10      1.1      uch  * Redistribution and use in source and binary forms, with or without
     11      1.1      uch  * modification, are permitted provided that the following conditions
     12      1.1      uch  * are met:
     13      1.1      uch  * 1. Redistributions of source code must retain the above copyright
     14      1.1      uch  *    notice, this list of conditions and the following disclaimer.
     15      1.1      uch  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1      uch  *    notice, this list of conditions and the following disclaimer in the
     17      1.1      uch  *    documentation and/or other materials provided with the distribution.
     18      1.1      uch  * 3. All advertising materials mentioning features or use of this software
     19      1.1      uch  *    must display the following acknowledgement:
     20      1.1      uch  *        This product includes software developed by the NetBSD
     21      1.1      uch  *        Foundation, Inc. and its contributors.
     22      1.1      uch  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.1      uch  *    contributors may be used to endorse or promote products derived
     24      1.1      uch  *    from this software without specific prior written permission.
     25      1.1      uch  *
     26      1.1      uch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.1      uch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.1      uch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.1      uch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.1      uch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.1      uch  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.1      uch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.1      uch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.1      uch  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.1      uch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.1      uch  * POSSIBILITY OF SUCH DAMAGE.
     37      1.1      uch  */
     38      1.1      uch 
     39      1.1      uch #include <load.h>
     40      1.1      uch #include <load_elf.h>
     41      1.1      uch #include <console.h>
     42      1.1      uch #include <memory.h>
     43      1.1      uch #include <file.h>
     44      1.1      uch 
     45      1.1      uch ElfLoader::ElfLoader(Console *&cons, MemoryManager *&mem)
     46      1.1      uch 	: Loader(cons, mem)
     47      1.1      uch {
     48      1.1      uch 	DPRINTF((TEXT("Loader: ELF\n")));
     49      1.1      uch }
     50      1.1      uch 
     51      1.1      uch ElfLoader::~ElfLoader(void)
     52      1.1      uch {
     53      1.1      uch }
     54      1.1      uch 
     55      1.1      uch BOOL
     56      1.1      uch ElfLoader::setFile(File *&file)
     57      1.1      uch {
     58  1.1.4.1  nathanw 	size_t sz;
     59      1.1      uch 	Loader::setFile(file);
     60      1.1      uch 
     61      1.1      uch 	/* read ELF header and check it */
     62      1.1      uch 	if (!read_header())
     63      1.1      uch 		return FALSE;
     64  1.1.4.1  nathanw 	/* read section header */
     65  1.1.4.1  nathanw 	sz = _eh.e_shnum * _eh.e_shentsize;
     66  1.1.4.1  nathanw 	_file->read(_sh, _eh.e_shentsize * _eh.e_shnum, _eh.e_shoff);
     67  1.1.4.1  nathanw 
     68      1.1      uch 	/* read program header */
     69  1.1.4.1  nathanw 	sz = _eh.e_phnum * _eh.e_phentsize;
     70      1.1      uch 
     71      1.1      uch 	return _file->read(_ph, sz, _eh.e_phoff) == sz;
     72      1.1      uch }
     73      1.1      uch 
     74      1.1      uch size_t
     75      1.1      uch ElfLoader::memorySize()
     76      1.1      uch {
     77      1.1      uch 	int i;
     78      1.1      uch 	Elf_Phdr *ph = _ph;
     79      1.1      uch 	size_t sz = 0;
     80      1.1      uch 
     81      1.1      uch 	DPRINTF((TEXT("file size: ")));
     82      1.1      uch 	for (i = 0; i < _eh.e_phnum; i++, ph++) {
     83      1.1      uch 		if (ph->p_type == PT_LOAD) {
     84      1.1      uch 			size_t filesz = ph->p_filesz;
     85      1.1      uch 			DPRINTF((TEXT("+0x%x"), filesz));
     86      1.1      uch 			sz += _mem->roundPage(filesz);
     87      1.1      uch 		}
     88      1.1      uch 	}
     89  1.1.4.1  nathanw 	/* XXX reserve 192kB for symbols */
     90  1.1.4.1  nathanw 	sz += 0x30000;
     91  1.1.4.1  nathanw 
     92      1.1      uch 	DPRINTF((TEXT(" = 0x%x byte\n"), sz));
     93      1.1      uch 	return sz;
     94      1.1      uch }
     95      1.1      uch 
     96      1.1      uch kaddr_t
     97      1.1      uch ElfLoader::jumpAddr()
     98      1.1      uch {
     99      1.1      uch 	DPRINTF((TEXT("kernel entry address: 0x%08x\n"), _eh.e_entry));
    100      1.1      uch 	return _eh.e_entry;
    101      1.1      uch }
    102      1.1      uch 
    103      1.1      uch BOOL
    104      1.1      uch ElfLoader::load()
    105      1.1      uch {
    106      1.1      uch 	Elf_Phdr *ph;
    107  1.1.4.1  nathanw 	Elf_Shdr *sh, *shstr, *shsym;
    108  1.1.4.1  nathanw 	off_t stroff = 0, symoff = 0, off;
    109  1.1.4.2  nathanw 	vaddr_t kv;
    110  1.1.4.2  nathanw 
    111  1.1.4.1  nathanw 	size_t shstrsize;
    112  1.1.4.1  nathanw 	char buf[1024];
    113      1.1      uch 	int i;
    114      1.1      uch 
    115      1.1      uch 	_load_segment_start();
    116      1.1      uch 
    117      1.1      uch 	for (i = 0, ph = _ph; i < _eh.e_phnum; i++, ph++) {
    118      1.1      uch 		if (ph->p_type == PT_LOAD) {
    119      1.1      uch 			size_t filesz = ph->p_filesz;
    120      1.1      uch 			size_t memsz = ph->p_memsz;
    121  1.1.4.1  nathanw 			kv = ph->p_vaddr;
    122      1.1      uch 			off_t fileofs = ph->p_offset;
    123      1.1      uch 			DPRINTF((TEXT("[%d] vaddr 0x%08x file size 0x%x mem size 0x%x\n"),
    124  1.1.4.2  nathanw 			    i, kv, filesz, memsz));
    125      1.1      uch 			_load_segment(kv, memsz, fileofs, filesz);
    126  1.1.4.1  nathanw 			kv += memsz;
    127  1.1.4.1  nathanw 		}
    128  1.1.4.1  nathanw 	}
    129  1.1.4.1  nathanw 
    130  1.1.4.1  nathanw 	/*
    131  1.1.4.1  nathanw 	 * Prepare ELF headers for symbol table.
    132  1.1.4.1  nathanw 	 *
    133  1.1.4.1  nathanw 	 *   ELF header
    134  1.1.4.1  nathanw 	 *   section header
    135  1.1.4.1  nathanw 	 *   shstrtab
    136  1.1.4.1  nathanw 	 *   strtab
    137  1.1.4.1  nathanw 	 *   symtab
    138  1.1.4.1  nathanw 	 */
    139  1.1.4.1  nathanw 	memcpy(buf, &_eh, sizeof(_eh));
    140  1.1.4.1  nathanw 	((Elf_Ehdr *)buf)->e_phoff = 0;
    141  1.1.4.1  nathanw 	((Elf_Ehdr *)buf)->e_phnum = 0;
    142  1.1.4.1  nathanw 	((Elf_Ehdr *)buf)->e_entry = 0;
    143  1.1.4.1  nathanw 	((Elf_Ehdr *)buf)->e_shoff = sizeof(_eh);
    144  1.1.4.1  nathanw 	off = ((Elf_Ehdr *)buf)->e_shoff;
    145  1.1.4.1  nathanw 	memcpy(buf + off, _sh, _eh.e_shentsize * _eh.e_shnum);
    146  1.1.4.1  nathanw 	sh = (Elf_Shdr *)(buf + off);
    147  1.1.4.1  nathanw 	off += _eh.e_shentsize * _eh.e_shnum;
    148  1.1.4.1  nathanw 
    149  1.1.4.1  nathanw 	/* load shstrtab and find desired sections */
    150  1.1.4.1  nathanw 	shstrsize = (sh[_eh.e_shstrndx].sh_size + 3) & ~0x3;
    151  1.1.4.1  nathanw 	_file->read(buf + off, shstrsize, sh[_eh.e_shstrndx].sh_offset);
    152  1.1.4.1  nathanw 	for(i = 0; i < _eh.e_shnum; i++, sh++) {
    153  1.1.4.1  nathanw 		if (strcmp(".strtab", buf + off + sh->sh_name) == 0) {
    154  1.1.4.1  nathanw 			stroff = sh->sh_offset;
    155  1.1.4.1  nathanw 			shstr = sh;
    156  1.1.4.1  nathanw 		} else if (strcmp(".symtab", buf + off + sh->sh_name) == 0) {
    157  1.1.4.1  nathanw 			symoff = sh->sh_offset;
    158  1.1.4.1  nathanw 			shsym = sh;
    159      1.1      uch 		}
    160  1.1.4.1  nathanw 		if (i == _eh.e_shstrndx)
    161  1.1.4.1  nathanw 			sh->sh_offset = off;
    162  1.1.4.1  nathanw 		else
    163  1.1.4.1  nathanw 			sh->sh_offset = 0;
    164      1.1      uch 	}
    165  1.1.4.1  nathanw 	/* silently return if strtab or symtab can't be found */
    166  1.1.4.1  nathanw 	if (! stroff || ! symoff)
    167  1.1.4.1  nathanw 		return TRUE;
    168  1.1.4.1  nathanw 
    169  1.1.4.1  nathanw 	shstr->sh_offset = off + shstrsize;
    170  1.1.4.1  nathanw 	shsym->sh_offset = off + shstrsize + ((shstr->sh_size + 3) & ~0x3);
    171  1.1.4.1  nathanw 	_load_memory(kv, off + shstrsize, buf);
    172  1.1.4.1  nathanw 	kv += off + shstrsize;
    173  1.1.4.1  nathanw 	_load_segment(kv, shstr->sh_size, stroff, shstr->sh_size);
    174  1.1.4.1  nathanw 	kv += (shstr->sh_size + 3) & ~0x3;
    175  1.1.4.1  nathanw 	_load_segment(kv, shsym->sh_size, symoff, shsym->sh_size);
    176  1.1.4.1  nathanw 
    177      1.1      uch 	/* tag chain still opening */
    178      1.1      uch 
    179      1.1      uch 	return TRUE;
    180      1.1      uch }
    181      1.1      uch 
    182      1.1      uch BOOL
    183      1.1      uch ElfLoader::read_header(void)
    184      1.1      uch {
    185      1.1      uch 	// read ELF header
    186      1.1      uch 	_file->read(&_eh, sizeof(Elf_Ehdr), 0);
    187      1.1      uch 
    188      1.1      uch 	// check ELF Magic.
    189      1.1      uch 	if (!is_elf_file()) {
    190      1.1      uch 		DPRINTF((TEXT("not a ELF file.\n")));
    191      1.1      uch 		return FALSE;
    192      1.1      uch 	}
    193      1.1      uch 
    194      1.1      uch 	// Windows CE is 32bit little-endian only.
    195      1.1      uch 	if (_eh.e_ident[EI_DATA] != ELFDATA2LSB ||
    196      1.1      uch 	    _eh.e_ident[EI_CLASS] != ELFCLASS32) {
    197      1.1      uch 		DPRINTF((TEXT("invalid class/data(%d/%d)\n"),
    198  1.1.4.2  nathanw 		    _eh.e_ident[EI_CLASS], _eh.e_ident[EI_DATA]));
    199      1.1      uch 		return FALSE;
    200      1.1      uch 	}
    201      1.1      uch 
    202      1.1      uch 	// Is native architecture?
    203      1.1      uch 	switch(_eh.e_machine) {
    204      1.1      uch 		ELF32_MACHDEP_ID_CASES;
    205      1.1      uch 	default:
    206      1.1      uch 		DPRINTF((TEXT("not a native architecture. machine = %d\n"),
    207  1.1.4.2  nathanw 		    _eh.e_machine));
    208      1.1      uch 		return FALSE;
    209      1.1      uch 	}
    210      1.1      uch 
    211      1.1      uch 	/* Check object type */
    212      1.1      uch 	if (_eh.e_type != ET_EXEC) {
    213      1.1      uch 		DPRINTF((TEXT("not a executable file. type = %d\n"),
    214  1.1.4.2  nathanw 		    _eh.e_type));
    215      1.1      uch 		return FALSE;
    216      1.1      uch 	}
    217      1.1      uch 
    218      1.1      uch 	if (_eh.e_phoff == 0 || _eh.e_phnum == 0 || _eh.e_phnum > 16 ||
    219      1.1      uch 	    _eh.e_phentsize != sizeof(Elf_Phdr)) {
    220      1.1      uch 		DPRINTF((TEXT("invalid program header infomation.\n")));
    221      1.1      uch 		return FALSE;
    222      1.1      uch 	}
    223      1.1      uch 
    224      1.1      uch 	return TRUE;
    225      1.1      uch }
    226