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 67 int 68 elf_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 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 if (*((u_int *)ehdr.e_ident) != ELFMAGIC) 83 return -1; 84 85 /* 86 * calculate highest used address 87 */ 88 i = ehdr.e_phnum * sizeof(Elf32_Phdr); 89 err = 1; 90 if ((phdrs = (Elf32_Phdr *)MALLOC(i)) == NULL) 91 goto error; 92 err = 2; 93 if (read(fd, phdrs, i) != i) 94 goto error; 95 96 kernsize = 0; 97 for (i = 0; i < ehdr.e_phnum; i++) { 98 Elf32_Word sum; 99 100 sum = phdrs[i].p_vaddr + phdrs[i].p_memsz; 101 if ((phdrs[i].p_flags & (PF_W|PF_X)) && (sum > kernsize)) 102 kernsize = sum; 103 } 104 105 /* 106 * look for symbols and calculate the size 107 * XXX: This increases the load time by a factor 2 for gzipped 108 * images! 109 */ 110 symsize = 0; 111 symstart = 0; 112 if (loadsyms) { 113 i = ehdr.e_shnum + 1; 114 err = 3; 115 if (lseek(fd, (off_t)ehdr.e_shoff, SEEK_SET) != ehdr.e_shoff) 116 goto error; 117 while (--i) { 118 Elf32_Shdr shdr; 119 120 err = 4; 121 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) 122 goto error; 123 if ((shdr.sh_type == SHT_SYMTAB) || (shdr.sh_type == SHT_STRTAB)) 124 symsize += shdr.sh_size; 125 } 126 } 127 128 if (symsize) { 129 symstart = kernsize; 130 kernsize += symsize + sizeof(ehdr) + ehdr.e_shnum*sizeof(Elf32_Shdr); 131 } 132 133 /* 134 * Extract various sizes from the kernel executable 135 */ 136 od->k_esym = symsize ? kernsize : 0; 137 od->ksize = kernsize; 138 od->kentry = ehdr.e_entry; 139 140 err = 5; 141 if ((od->kstart = (u_char *)MALLOC(od->ksize)) == NULL) 142 goto error; 143 144 /* 145 * Read text & data, clear bss 146 */ 147 for (i = 0; i < ehdr.e_phnum; i++) { 148 u_char *p; 149 Elf32_Phdr *php = &phdrs[i]; 150 151 if (php->p_flags & (PF_W|PF_X)) { 152 err = 6; 153 if (lseek(fd, (off_t)php->p_offset, SEEK_SET) != php->p_offset) 154 goto error; 155 p = (u_char *)(od->kstart) + php->p_vaddr; 156 err = 7; 157 if (read(fd, p, php->p_filesz) != php->p_filesz) 158 goto error; 159 if (php->p_memsz > php->p_filesz) 160 memset(p + php->p_filesz, 0, php->p_memsz - php->p_filesz); 161 } 162 } 163 164 /* 165 * Read symbols and strings 166 */ 167 if (symsize) { 168 u_char *p, *symtab; 169 int nhdrs; 170 Elf32_Shdr *shp; 171 172 symtab = od->kstart + symstart; 173 174 p = symtab + sizeof(ehdr); 175 nhdrs = ehdr.e_shnum; 176 err = 8; 177 if (lseek(fd, (off_t)ehdr.e_shoff, SEEK_SET) != ehdr.e_shoff) 178 goto error; 179 err = 9; 180 if (read(fd, p, nhdrs * sizeof(*shp)) != nhdrs * sizeof(*shp)) 181 goto error; 182 shp = (Elf32_Shdr*)p; 183 p += nhdrs * sizeof(*shp); 184 for (i = 0; i < nhdrs; i++) { 185 if (shp[i].sh_type == SHT_SYMTAB) { 186 if (shp[i].sh_offset == 0) 187 continue; 188 /* Got the symbol table. */ 189 err = 10; 190 if (lseek(fd, (off_t)shp[i].sh_offset, SEEK_SET) != 191 shp[i].sh_offset) 192 goto error; 193 err = 11; 194 if (read(fd, p, shp[i].sh_size) != shp[i].sh_size) 195 goto error; 196 shp[i].sh_offset = p - symtab; 197 /* Find the string table to go with it. */ 198 j = shp[i].sh_link; 199 if (shp[j].sh_offset == 0) 200 continue; 201 p += shp[i].sh_size; 202 err = 12; 203 if (lseek(fd, (off_t)shp[j].sh_offset, SEEK_SET) != 204 shp[j].sh_offset) 205 goto error; 206 err = 13; 207 if (read(fd, p, shp[j].sh_size) != shp[j].sh_size) 208 goto error; 209 shp[j].sh_offset = p - symtab; 210 /* There should only be one symbol table. */ 211 break; 212 } 213 } 214 ehdr.e_shoff = sizeof(ehdr); 215 memcpy(symtab, &ehdr, sizeof(ehdr)); 216 } 217 return 0; 218 219 error: 220 #ifdef TOSTOOLS 221 { 222 static char *errs[] = { 223 /* 1 */ "Cannot malloc Elf phdr storage space", 224 /* 2 */ "Cannot read Elf32_Phdrs", 225 /* 3 */ "Cannot seek to e_shoff location", 226 /* 4 */ "Cannot read Elf32_shdr", 227 /* 5 */ "Cannot malloc kernel image space", 228 /* 6 */ "Seek error while reading text segment\n", 229 /* 7 */ "Read error in text segment\n", 230 /* 8 */ "Error seeking to section headers", 231 /* 9 */ "Error reading section headers", 232 /* 10 */ "Error seeking to symbols", 233 /* 11 */ "Error reading symbols", 234 /* 12 */ "Error seeking to string table", 235 /* 13 */ "Error reading strings" 236 }; 237 *errp = errs[err]; 238 } 239 #endif /* TOSTOOLS */ 240 241 return err; 242 } 243