win32 fix
[qemu] / loader.c
1 /*
2  * QEMU Executable loader
3  * 
4  * Copyright (c) 2006 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25 #include "disas.h"
26
27 /* return the size or -1 if error */
28 int get_image_size(const char *filename)
29 {
30     int fd, size;
31     fd = open(filename, O_RDONLY | O_BINARY);
32     if (fd < 0)
33         return -1;
34     size = lseek(fd, 0, SEEK_END);
35     close(fd);
36     return size;
37 }
38
39 /* return the size or -1 if error */
40 int load_image(const char *filename, uint8_t *addr)
41 {
42     int fd, size;
43     fd = open(filename, O_RDONLY | O_BINARY);
44     if (fd < 0)
45         return -1;
46     size = lseek(fd, 0, SEEK_END);
47     lseek(fd, 0, SEEK_SET);
48     if (read(fd, addr, size) != size) {
49         close(fd);
50         return -1;
51     }
52     close(fd);
53     return size;
54 }
55
56 /* A.OUT loader */
57
58 struct exec
59 {
60   uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
61   uint32_t a_text;   /* length of text, in bytes */
62   uint32_t a_data;   /* length of data, in bytes */
63   uint32_t a_bss;    /* length of uninitialized data area, in bytes */
64   uint32_t a_syms;   /* length of symbol table data in file, in bytes */
65   uint32_t a_entry;  /* start address */
66   uint32_t a_trsize; /* length of relocation info for text, in bytes */
67   uint32_t a_drsize; /* length of relocation info for data, in bytes */
68 };
69
70 #ifdef BSWAP_NEEDED
71 static void bswap_ahdr(struct exec *e)
72 {
73     bswap32s(&e->a_info);
74     bswap32s(&e->a_text);
75     bswap32s(&e->a_data);
76     bswap32s(&e->a_bss);
77     bswap32s(&e->a_syms);
78     bswap32s(&e->a_entry);
79     bswap32s(&e->a_trsize);
80     bswap32s(&e->a_drsize);
81 }
82 #else
83 #define bswap_ahdr(x) do { } while (0)
84 #endif
85
86 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
87 #define OMAGIC 0407
88 #define NMAGIC 0410
89 #define ZMAGIC 0413
90 #define QMAGIC 0314
91 #define _N_HDROFF(x) (1024 - sizeof (struct exec))
92 #define N_TXTOFF(x)                                                     \
93     (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :     \
94      (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
95 #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
96 #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
97 #define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
98
99 #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
100
101 #define N_DATADDR(x) \
102     (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
103      : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
104
105
106 int load_aout(const char *filename, uint8_t *addr)
107 {
108     int fd, size, ret;
109     struct exec e;
110     uint32_t magic;
111
112     fd = open(filename, O_RDONLY | O_BINARY);
113     if (fd < 0)
114         return -1;
115
116     size = read(fd, &e, sizeof(e));
117     if (size < 0)
118         goto fail;
119
120     bswap_ahdr(&e);
121
122     magic = N_MAGIC(e);
123     switch (magic) {
124     case ZMAGIC:
125     case QMAGIC:
126     case OMAGIC:
127         lseek(fd, N_TXTOFF(e), SEEK_SET);
128         size = read(fd, addr, e.a_text + e.a_data);
129         if (size < 0)
130             goto fail;
131         break;
132     case NMAGIC:
133         lseek(fd, N_TXTOFF(e), SEEK_SET);
134         size = read(fd, addr, e.a_text);
135         if (size < 0)
136             goto fail;
137         ret = read(fd, addr + N_DATADDR(e), e.a_data);
138         if (ret < 0)
139             goto fail;
140         size += ret;
141         break;
142     default:
143         goto fail;
144     }
145     close(fd);
146     return size;
147  fail:
148     close(fd);
149     return -1;
150 }
151
152 /* ELF loader */
153
154 static void *load_at(int fd, int offset, int size)
155 {
156     void *ptr;
157     if (lseek(fd, offset, SEEK_SET) < 0)
158         return NULL;
159     ptr = qemu_malloc(size);
160     if (!ptr)
161         return NULL;
162     if (read(fd, ptr, size) != size) {
163         qemu_free(ptr);
164         return NULL;
165     }
166     return ptr;
167 }
168
169
170 #define ELF_CLASS   ELFCLASS32
171 #include "elf.h"
172
173 #define SZ              32
174 #define elf_word        uint32_t
175 #define bswapSZs        bswap32s
176 #include "elf_ops.h"
177
178 #undef elfhdr
179 #undef elf_phdr
180 #undef elf_shdr
181 #undef elf_sym
182 #undef elf_note
183 #undef elf_word
184 #undef bswapSZs
185 #undef SZ
186 #define elfhdr          elf64_hdr
187 #define elf_phdr        elf64_phdr
188 #define elf_note        elf64_note
189 #define elf_shdr        elf64_shdr
190 #define elf_sym         elf64_sym
191 #define elf_word        uint64_t
192 #define bswapSZs        bswap64s
193 #define SZ              64
194 #include "elf_ops.h"
195
196 /* return < 0 if error, otherwise the number of bytes loaded in memory */
197 int load_elf(const char *filename, int64_t virt_to_phys_addend,
198              uint64_t *pentry)
199 {
200     int fd, data_order, must_swab, ret;
201     uint8_t e_ident[EI_NIDENT];
202
203     fd = open(filename, O_RDONLY | O_BINARY);
204     if (fd < 0) {
205         perror(filename);
206         return -1;
207     }
208     if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
209         goto fail;
210     if (e_ident[0] != ELFMAG0 ||
211         e_ident[1] != ELFMAG1 ||
212         e_ident[2] != ELFMAG2 ||
213         e_ident[3] != ELFMAG3)
214         goto fail;
215 #ifdef WORDS_BIGENDIAN
216     data_order = ELFDATA2MSB;
217 #else
218     data_order = ELFDATA2LSB;
219 #endif
220     must_swab = data_order != e_ident[EI_DATA];
221     
222     lseek(fd, 0, SEEK_SET);
223     if (e_ident[EI_CLASS] == ELFCLASS64) {
224         ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry);
225     } else {
226         ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry);
227     }
228
229     close(fd);
230     return ret;
231
232  fail:
233     close(fd);
234     return -1;
235 }