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