1/* $NetBSD: elf.c,v 1.13 2009/03/31 11:48:15 tsutsui Exp $ */ 2 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Leo Weppelman. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#ifdef TOSTOOLS 33#include <stdio.h> 34#include <stdlib.h> 35#include <unistd.h> 36#include <string.h> 37#include <sys/types.h> 38#include "exec_elf.h" 39 40#define MALLOC(x) malloc(x) 41 42#else 43 44#include <lib/libsa/stand.h> 45#include <atari_stand.h> 46#include <libkern.h> 47#include <sys/exec_elf.h> 48 49#define MALLOC(x) alloc(x) 50#endif 51 52#include "libtos.h" 53#include "tosdefs.h" 54#include "kparamb.h" 55#include "cread.h" 56 57/* 58 * Load an elf image. 59 * Exit codes: 60 * -1 : Not an ELF file. 61 * 0 : OK 62 * error# : Error during load (*errp might contain error string). 63 */ 64#define ELFMAGIC ((ELFMAG0 << 24) | (ELFMAG1 << 16) | \ 65 (ELFMAG2 << 8) | ELFMAG3) 66 67int 68elf_load(int fd, osdsc_t *od, char **errp, int loadsyms) 69{ 70 int i,j; 71 int err; 72 Elf32_Ehdr ehdr; 73 Elf32_Phdr *phdrs; 74 Elf32_Word ident, symsize, symstart; 75 long kernsize; 76 77 *errp = NULL; 78 lseek(fd, (off_t)0, SEEK_SET); 79 if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) 80 return -1; 81 82 memcpy(&ident, ehdr.e_ident, sizeof ident); 83 if (ident != ELFMAGIC) 84 return -1; 85 86 /* 87 * calculate highest used address 88 */ 89 i = ehdr.e_phnum * sizeof(Elf32_Phdr); 90 err = 1; 91 if ((phdrs = (Elf32_Phdr *)MALLOC(i)) == NULL) 92 goto error; 93 err = 2; 94 if (read(fd, phdrs, i) != i) 95 goto error; 96 97 kernsize = 0; 98 for (i = 0; i < ehdr.e_phnum; i++) { 99 Elf32_Word sum; 100 101 sum = phdrs[i].p_vaddr + phdrs[i].p_memsz; 102 if ((phdrs[i].p_flags & (PF_W|PF_X)) && (sum > kernsize)) 103 kernsize = sum; 104 } 105 106 /* 107 * look for symbols and calculate the size 108 * XXX: This increases the load time by a factor 2 for gzipped 109 * images! 110 */ 111 symsize = 0; 112 symstart = 0; 113 if (loadsyms) { 114 i = ehdr.e_shnum + 1; 115 err = 3; 116 if (lseek(fd, (off_t)ehdr.e_shoff, SEEK_SET) != ehdr.e_shoff) 117 goto error; 118 while (--i) { 119 Elf32_Shdr shdr; 120 121 err = 4; 122 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) 123 goto error; 124 if ((shdr.sh_type == SHT_SYMTAB) || (shdr.sh_type == SHT_STRTAB)) 125 symsize += shdr.sh_size; 126 } 127 } 128 129 if (symsize) { 130 symstart = kernsize; 131 kernsize += symsize + sizeof(ehdr) + ehdr.e_shnum*sizeof(Elf32_Shdr); 132 } 133 134 /* 135 * Extract various sizes from the kernel executable 136 */ 137 od->k_esym = symsize ? kernsize : 0; 138 od->ksize = kernsize; 139 od->kentry = ehdr.e_entry; 140 141 err = 5; 142 if ((od->kstart = (u_char *)MALLOC(od->ksize)) == NULL) 143 goto error; 144 145 /* 146 * Read text & data, clear bss 147 */ 148 for (i = 0; i < ehdr.e_phnum; i++) { 149 u_char *p; 150 Elf32_Phdr *php = &phdrs[i]; 151 152 if (php->p_flags & (PF_W|PF_X)) { 153 err = 6; 154 if (lseek(fd, (off_t)php->p_offset, SEEK_SET) != php->p_offset) 155 goto error; 156 p = (u_char *)(od->kstart) + php->p_vaddr; 157 err = 7; 158 if (read(fd, p, php->p_filesz) != php->p_filesz) 159 goto error; 160 if (php->p_memsz > php->p_filesz) 161 memset(p + php->p_filesz, 0, php->p_memsz - php->p_filesz); 162 } 163 } 164 165 /* 166 * Read symbols and strings 167 */ 168 if (symsize) { 169 u_char *p, *symtab; 170 int nhdrs; 171 Elf32_Shdr *shp; 172 173 symtab = od->kstart + symstart; 174 175 p = symtab + sizeof(ehdr); 176 nhdrs = ehdr.e_shnum; 177 err = 8; 178 if (lseek(fd, (off_t)ehdr.e_shoff, SEEK_SET) != ehdr.e_shoff) 179 goto error; 180 err = 9; 181 if (read(fd, p, nhdrs * sizeof(*shp)) != nhdrs * sizeof(*shp)) 182 goto error; 183 shp = (Elf32_Shdr*)p; 184 p += nhdrs * sizeof(*shp); 185 for (i = 0; i < nhdrs; i++) { 186 if (shp[i].sh_type == SHT_SYMTAB) { 187 if (shp[i].sh_offset == 0) 188 continue; 189 /* Got the symbol table. */ 190 err = 10; 191 if (lseek(fd, (off_t)shp[i].sh_offset, SEEK_SET) != 192 shp[i].sh_offset) 193 goto error; 194 err = 11; 195 if (read(fd, p, shp[i].sh_size) != shp[i].sh_size) 196 goto error; 197 shp[i].sh_offset = p - symtab; 198 /* Find the string table to go with it. */ 199 j = shp[i].sh_link; 200 if (shp[j].sh_offset == 0) 201 continue; 202 p += shp[i].sh_size; 203 err = 12; 204 if (lseek(fd, (off_t)shp[j].sh_offset, SEEK_SET) != 205 shp[j].sh_offset) 206 goto error; 207 err = 13; 208 if (read(fd, p, shp[j].sh_size) != shp[j].sh_size) 209 goto error; 210 shp[j].sh_offset = p - symtab; 211 /* There should only be one symbol table. */ 212 break; 213 } 214 } 215 ehdr.e_shoff = sizeof(ehdr); 216 memcpy(symtab, &ehdr, sizeof(ehdr)); 217 } 218 return 0; 219 220error: 221#ifdef TOSTOOLS 222 { 223 static char *errs[] = { 224 /* 1 */ "Cannot malloc Elf phdr storage space", 225 /* 2 */ "Cannot read Elf32_Phdrs", 226 /* 3 */ "Cannot seek to e_shoff location", 227 /* 4 */ "Cannot read Elf32_shdr", 228 /* 5 */ "Cannot malloc kernel image space", 229 /* 6 */ "Seek error while reading text segment\n", 230 /* 7 */ "Read error in text segment\n", 231 /* 8 */ "Error seeking to section headers", 232 /* 9 */ "Error reading section headers", 233 /* 10 */ "Error seeking to symbols", 234 /* 11 */ "Error reading symbols", 235 /* 12 */ "Error seeking to string table", 236 /* 13 */ "Error reading strings" 237 }; 238 *errp = errs[err]; 239 } 240#endif /* TOSTOOLS */ 241 242 return err; 243} 244