1 /* $NetBSD: elf.c,v 1.12 2009/03/18 17:06:43 cegger Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
37 #include <sys/types.h>
40 #define MALLOC(x) malloc(x)
44 #include <lib/libsa/stand.h>
45 #include <atari_stand.h>
47 #include <sys/exec_elf.h>
49 #define MALLOC(x) alloc(x)
60 * -1 : Not an ELF file.
62 * error# : Error during load (*errp might contain error string).
64 #define ELFMAGIC ((ELFMAG0 << 24) | (ELFMAG1 << 16) | \
65 (ELFMAG2 << 8) | ELFMAG3)
68 elf_load(int fd
, osdsc_t
*od
, char **errp
, int loadsyms
)
74 Elf32_Word symsize
, symstart
;
78 lseek(fd
, (off_t
)0, SEEK_SET
);
79 if (read(fd
, (char *)&ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
82 if (*((u_int
*)ehdr
.e_ident
) != ELFMAGIC
)
86 * calculate highest used address
88 i
= ehdr
.e_phnum
* sizeof(Elf32_Phdr
);
90 if ((phdrs
= (Elf32_Phdr
*)MALLOC(i
)) == NULL
)
93 if (read(fd
, phdrs
, i
) != i
)
97 for (i
= 0; i
< ehdr
.e_phnum
; i
++) {
100 sum
= phdrs
[i
].p_vaddr
+ phdrs
[i
].p_memsz
;
101 if ((phdrs
[i
].p_flags
& (PF_W
|PF_X
)) && (sum
> kernsize
))
106 * look for symbols and calculate the size
107 * XXX: This increases the load time by a factor 2 for gzipped
113 i
= ehdr
.e_shnum
+ 1;
115 if (lseek(fd
, (off_t
)ehdr
.e_shoff
, SEEK_SET
) != ehdr
.e_shoff
)
121 if (read(fd
, &shdr
, sizeof(shdr
)) != sizeof(shdr
))
123 if ((shdr
.sh_type
== SHT_SYMTAB
) || (shdr
.sh_type
== SHT_STRTAB
))
124 symsize
+= shdr
.sh_size
;
130 kernsize
+= symsize
+ sizeof(ehdr
) + ehdr
.e_shnum
*sizeof(Elf32_Shdr
);
134 * Extract various sizes from the kernel executable
136 od
->k_esym
= symsize
? kernsize
: 0;
137 od
->ksize
= kernsize
;
138 od
->kentry
= ehdr
.e_entry
;
141 if ((od
->kstart
= (u_char
*)MALLOC(od
->ksize
)) == NULL
)
145 * Read text & data, clear bss
147 for (i
= 0; i
< ehdr
.e_phnum
; i
++) {
149 Elf32_Phdr
*php
= &phdrs
[i
];
151 if (php
->p_flags
& (PF_W
|PF_X
)) {
153 if (lseek(fd
, (off_t
)php
->p_offset
, SEEK_SET
) != php
->p_offset
)
155 p
= (u_char
*)(od
->kstart
) + php
->p_vaddr
;
157 if (read(fd
, p
, php
->p_filesz
) != php
->p_filesz
)
159 if (php
->p_memsz
> php
->p_filesz
)
160 memset(p
+ php
->p_filesz
, 0, php
->p_memsz
- php
->p_filesz
);
165 * Read symbols and strings
172 symtab
= od
->kstart
+ symstart
;
174 p
= symtab
+ sizeof(ehdr
);
175 nhdrs
= ehdr
.e_shnum
;
177 if (lseek(fd
, (off_t
)ehdr
.e_shoff
, SEEK_SET
) != ehdr
.e_shoff
)
180 if (read(fd
, p
, nhdrs
* sizeof(*shp
)) != nhdrs
* sizeof(*shp
))
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)
188 /* Got the symbol table. */
190 if (lseek(fd
, (off_t
)shp
[i
].sh_offset
, SEEK_SET
) !=
194 if (read(fd
, p
, shp
[i
].sh_size
) != shp
[i
].sh_size
)
196 shp
[i
].sh_offset
= p
- symtab
;
197 /* Find the string table to go with it. */
199 if (shp
[j
].sh_offset
== 0)
203 if (lseek(fd
, (off_t
)shp
[j
].sh_offset
, SEEK_SET
) !=
207 if (read(fd
, p
, shp
[j
].sh_size
) != shp
[j
].sh_size
)
209 shp
[j
].sh_offset
= p
- symtab
;
210 /* There should only be one symbol table. */
214 ehdr
.e_shoff
= sizeof(ehdr
);
215 memcpy(symtab
, &ehdr
, sizeof(ehdr
));
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"
239 #endif /* TOSTOOLS */