Statistics
| Branch: | Revision:

root / loader.c @ 5fe141fd

History | View | Annotate | Download (5.9 kB)

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
{
199
    int fd, data_order, must_swab, ret;
200
    uint8_t e_ident[EI_NIDENT];
201

    
202
    fd = open(filename, O_RDONLY);
203
    if (fd < 0) {
204
        perror(filename);
205
        return -1;
206
    }
207
    if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
208
        goto fail;
209
    if (e_ident[0] != ELFMAG0 ||
210
        e_ident[1] != ELFMAG1 ||
211
        e_ident[2] != ELFMAG2 ||
212
        e_ident[3] != ELFMAG3)
213
        goto fail;
214
#ifdef WORDS_BIGENDIAN
215
    data_order = ELFDATA2MSB;
216
#else
217
    data_order = ELFDATA2LSB;
218
#endif
219
    must_swab = data_order != e_ident[EI_DATA];
220
    
221
    lseek(fd, 0, SEEK_SET);
222
    if (e_ident[EI_CLASS] == ELFCLASS64) {
223
        ret = load_elf64(fd, virt_to_phys_addend, must_swab);
224
    } else {
225
        ret = load_elf32(fd, virt_to_phys_addend, must_swab);
226
    }
227

    
228
    close(fd);
229
    return ret;
230

    
231
 fail:
232
    close(fd);
233
    return -1;
234
}