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