Statistics
| Branch: | Revision:

root / hw / magic-load.c @ cadae95f

History | View | Annotate | Download (8.3 kB)

1 420557e8 bellard
#include "vl.h"
2 420557e8 bellard
#include "disas.h"
3 e80cfcfc bellard
#include "exec-all.h"
4 e80cfcfc bellard
5 e80cfcfc bellard
struct exec
6 e80cfcfc bellard
{
7 e80cfcfc bellard
  uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
8 e80cfcfc bellard
  uint32_t a_text;   /* length of text, in bytes */
9 e80cfcfc bellard
  uint32_t a_data;   /* length of data, in bytes */
10 e80cfcfc bellard
  uint32_t a_bss;    /* length of uninitialized data area, in bytes */
11 e80cfcfc bellard
  uint32_t a_syms;   /* length of symbol table data in file, in bytes */
12 e80cfcfc bellard
  uint32_t a_entry;  /* start address */
13 e80cfcfc bellard
  uint32_t a_trsize; /* length of relocation info for text, in bytes */
14 e80cfcfc bellard
  uint32_t a_drsize; /* length of relocation info for data, in bytes */
15 e80cfcfc bellard
};
16 e80cfcfc bellard
17 e80cfcfc bellard
#ifdef BSWAP_NEEDED
18 e80cfcfc bellard
static void bswap_ahdr(struct exec *e)
19 e80cfcfc bellard
{
20 e80cfcfc bellard
    bswap32s(&e->a_info);
21 e80cfcfc bellard
    bswap32s(&e->a_text);
22 e80cfcfc bellard
    bswap32s(&e->a_data);
23 e80cfcfc bellard
    bswap32s(&e->a_bss);
24 e80cfcfc bellard
    bswap32s(&e->a_syms);
25 e80cfcfc bellard
    bswap32s(&e->a_entry);
26 e80cfcfc bellard
    bswap32s(&e->a_trsize);
27 e80cfcfc bellard
    bswap32s(&e->a_drsize);
28 e80cfcfc bellard
}
29 e80cfcfc bellard
#else
30 e80cfcfc bellard
#define bswap_ahdr(x) do { } while (0)
31 e80cfcfc bellard
#endif
32 e80cfcfc bellard
33 e80cfcfc bellard
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
34 e80cfcfc bellard
#define OMAGIC 0407
35 e80cfcfc bellard
#define NMAGIC 0410
36 e80cfcfc bellard
#define ZMAGIC 0413
37 e80cfcfc bellard
#define QMAGIC 0314
38 e80cfcfc bellard
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
39 e80cfcfc bellard
#define N_TXTOFF(x)                                                        \
40 e80cfcfc bellard
    (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :        \
41 e80cfcfc bellard
     (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
42 e80cfcfc bellard
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
43 e80cfcfc bellard
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
44 e80cfcfc bellard
#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
45 e80cfcfc bellard
46 e80cfcfc bellard
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
47 e80cfcfc bellard
48 e80cfcfc bellard
#define N_DATADDR(x) \
49 e80cfcfc bellard
    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
50 e80cfcfc bellard
     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
51 e80cfcfc bellard
52 420557e8 bellard
53 420557e8 bellard
#define ELF_CLASS   ELFCLASS32
54 420557e8 bellard
#define ELF_DATA    ELFDATA2MSB
55 420557e8 bellard
#define ELF_ARCH    EM_SPARC
56 420557e8 bellard
57 420557e8 bellard
#include "elf.h"
58 420557e8 bellard
59 420557e8 bellard
#ifdef BSWAP_NEEDED
60 420557e8 bellard
static void bswap_ehdr(Elf32_Ehdr *ehdr)
61 420557e8 bellard
{
62 420557e8 bellard
    bswap16s(&ehdr->e_type);                        /* Object file type */
63 420557e8 bellard
    bswap16s(&ehdr->e_machine);                /* Architecture */
64 420557e8 bellard
    bswap32s(&ehdr->e_version);                /* Object file version */
65 420557e8 bellard
    bswap32s(&ehdr->e_entry);                /* Entry point virtual address */
66 420557e8 bellard
    bswap32s(&ehdr->e_phoff);                /* Program header table file offset */
67 420557e8 bellard
    bswap32s(&ehdr->e_shoff);                /* Section header table file offset */
68 420557e8 bellard
    bswap32s(&ehdr->e_flags);                /* Processor-specific flags */
69 420557e8 bellard
    bswap16s(&ehdr->e_ehsize);                /* ELF header size in bytes */
70 420557e8 bellard
    bswap16s(&ehdr->e_phentsize);                /* Program header table entry size */
71 420557e8 bellard
    bswap16s(&ehdr->e_phnum);                /* Program header table entry count */
72 420557e8 bellard
    bswap16s(&ehdr->e_shentsize);                /* Section header table entry size */
73 420557e8 bellard
    bswap16s(&ehdr->e_shnum);                /* Section header table entry count */
74 420557e8 bellard
    bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
75 420557e8 bellard
}
76 420557e8 bellard
77 420557e8 bellard
static void bswap_phdr(Elf32_Phdr *phdr)
78 420557e8 bellard
{
79 420557e8 bellard
    bswap32s(&phdr->p_type);                        /* Segment type */
80 420557e8 bellard
    bswap32s(&phdr->p_offset);                /* Segment file offset */
81 420557e8 bellard
    bswap32s(&phdr->p_vaddr);                /* Segment virtual address */
82 420557e8 bellard
    bswap32s(&phdr->p_paddr);                /* Segment physical address */
83 420557e8 bellard
    bswap32s(&phdr->p_filesz);                /* Segment size in file */
84 420557e8 bellard
    bswap32s(&phdr->p_memsz);                /* Segment size in memory */
85 420557e8 bellard
    bswap32s(&phdr->p_flags);                /* Segment flags */
86 420557e8 bellard
    bswap32s(&phdr->p_align);                /* Segment alignment */
87 420557e8 bellard
}
88 420557e8 bellard
89 420557e8 bellard
static void bswap_shdr(Elf32_Shdr *shdr)
90 420557e8 bellard
{
91 420557e8 bellard
    bswap32s(&shdr->sh_name);
92 420557e8 bellard
    bswap32s(&shdr->sh_type);
93 420557e8 bellard
    bswap32s(&shdr->sh_flags);
94 420557e8 bellard
    bswap32s(&shdr->sh_addr);
95 420557e8 bellard
    bswap32s(&shdr->sh_offset);
96 420557e8 bellard
    bswap32s(&shdr->sh_size);
97 420557e8 bellard
    bswap32s(&shdr->sh_link);
98 420557e8 bellard
    bswap32s(&shdr->sh_info);
99 420557e8 bellard
    bswap32s(&shdr->sh_addralign);
100 420557e8 bellard
    bswap32s(&shdr->sh_entsize);
101 420557e8 bellard
}
102 420557e8 bellard
103 420557e8 bellard
static void bswap_sym(Elf32_Sym *sym)
104 420557e8 bellard
{
105 420557e8 bellard
    bswap32s(&sym->st_name);
106 420557e8 bellard
    bswap32s(&sym->st_value);
107 420557e8 bellard
    bswap32s(&sym->st_size);
108 420557e8 bellard
    bswap16s(&sym->st_shndx);
109 420557e8 bellard
}
110 8d5f07fa bellard
#else
111 8d5f07fa bellard
#define bswap_ehdr(e) do { } while (0)
112 8d5f07fa bellard
#define bswap_phdr(e) do { } while (0)
113 8d5f07fa bellard
#define bswap_shdr(e) do { } while (0)
114 8d5f07fa bellard
#define bswap_sym(e) do { } while (0)
115 420557e8 bellard
#endif
116 420557e8 bellard
117 8d5f07fa bellard
static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
118 420557e8 bellard
{
119 8d5f07fa bellard
    int i, retval;
120 8d5f07fa bellard
121 8d5f07fa bellard
    retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
122 8d5f07fa bellard
    if (retval < 0)
123 8d5f07fa bellard
        return -1;
124 8d5f07fa bellard
125 8d5f07fa bellard
    for (i = 0; i < ehdr->e_phnum; i++) {
126 8d5f07fa bellard
        retval = read(fd, phdr, sizeof(*phdr));
127 8d5f07fa bellard
        if (retval < 0)
128 8d5f07fa bellard
            return -1;
129 8d5f07fa bellard
        bswap_phdr(phdr);
130 8d5f07fa bellard
        if (phdr->p_type == type)
131 8d5f07fa bellard
            return 0;
132 420557e8 bellard
    }
133 8d5f07fa bellard
    return -1;
134 420557e8 bellard
}
135 420557e8 bellard
136 8d5f07fa bellard
static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
137 420557e8 bellard
{
138 8d5f07fa bellard
    int i, retval;
139 8d5f07fa bellard
140 8d5f07fa bellard
    retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
141 8d5f07fa bellard
    if (retval < 0)
142 8d5f07fa bellard
        return NULL;
143 8d5f07fa bellard
144 8d5f07fa bellard
    for (i = 0; i < ehdr->e_shnum; i++) {
145 8d5f07fa bellard
        retval = read(fd, shdr, sizeof(*shdr));
146 8d5f07fa bellard
        if (retval < 0)
147 8d5f07fa bellard
            return NULL;
148 8d5f07fa bellard
        bswap_shdr(shdr);
149 8d5f07fa bellard
        if (shdr->sh_type == type)
150 8d5f07fa bellard
            return qemu_malloc(shdr->sh_size);
151 420557e8 bellard
    }
152 8d5f07fa bellard
    return NULL;
153 8d5f07fa bellard
}
154 420557e8 bellard
155 e80cfcfc bellard
static void *find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
156 8d5f07fa bellard
{
157 8d5f07fa bellard
    int retval;
158 420557e8 bellard
159 8d5f07fa bellard
    retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
160 8d5f07fa bellard
    if (retval < 0)
161 e80cfcfc bellard
        return NULL;
162 8d5f07fa bellard
163 8d5f07fa bellard
    retval = read(fd, shdr, sizeof(*shdr));
164 8d5f07fa bellard
    if (retval < 0)
165 e80cfcfc bellard
        return NULL;
166 8d5f07fa bellard
    bswap_shdr(shdr);
167 8d5f07fa bellard
    if (shdr->sh_type == SHT_STRTAB)
168 8d5f07fa bellard
        return qemu_malloc(shdr->sh_size);;
169 e80cfcfc bellard
    return NULL;
170 420557e8 bellard
}
171 420557e8 bellard
172 e80cfcfc bellard
static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
173 420557e8 bellard
{
174 420557e8 bellard
    int retval;
175 e80cfcfc bellard
    retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
176 8d5f07fa bellard
    if (retval < 0)
177 8d5f07fa bellard
        return -1;
178 8d5f07fa bellard
    return read(fd, dst, phdr->p_filesz);
179 8d5f07fa bellard
}
180 420557e8 bellard
181 8d5f07fa bellard
static int read_section(int fd, struct elf_shdr *s, void *dst)
182 8d5f07fa bellard
{
183 8d5f07fa bellard
    int retval;
184 420557e8 bellard
185 8d5f07fa bellard
    retval = lseek(fd, s->sh_offset, SEEK_SET);
186 8d5f07fa bellard
    if (retval < 0)
187 8d5f07fa bellard
        return -1;
188 8d5f07fa bellard
    retval = read(fd, dst, s->sh_size);
189 8d5f07fa bellard
    if (retval < 0)
190 8d5f07fa bellard
        return -1;
191 8d5f07fa bellard
    return 0;
192 8d5f07fa bellard
}
193 420557e8 bellard
194 8d5f07fa bellard
static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
195 8d5f07fa bellard
{
196 8d5f07fa bellard
    void *dst;
197 8d5f07fa bellard
198 8d5f07fa bellard
    dst = find_shdr(ehdr, fd, shdr, type);
199 8d5f07fa bellard
    if (!dst)
200 8d5f07fa bellard
        goto error;
201 8d5f07fa bellard
202 8d5f07fa bellard
    if (read_section(fd, shdr, dst))
203 8d5f07fa bellard
        goto error;
204 8d5f07fa bellard
    return dst;
205 8d5f07fa bellard
 error:
206 8d5f07fa bellard
    qemu_free(dst);
207 8d5f07fa bellard
    return NULL;
208 8d5f07fa bellard
}
209 420557e8 bellard
210 8d5f07fa bellard
static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
211 8d5f07fa bellard
{
212 8d5f07fa bellard
    void *dst;
213 8d5f07fa bellard
214 8d5f07fa bellard
    dst = find_strtab(ehdr, fd, shdr, symtab);
215 8d5f07fa bellard
    if (!dst)
216 8d5f07fa bellard
        goto error;
217 8d5f07fa bellard
218 8d5f07fa bellard
    if (read_section(fd, shdr, dst))
219 8d5f07fa bellard
        goto error;
220 8d5f07fa bellard
    return dst;
221 8d5f07fa bellard
 error:
222 8d5f07fa bellard
    qemu_free(dst);
223 8d5f07fa bellard
    return NULL;
224 8d5f07fa bellard
}
225 420557e8 bellard
226 8d5f07fa bellard
static void load_symbols(struct elfhdr *ehdr, int fd)
227 8d5f07fa bellard
{
228 8d5f07fa bellard
    struct elf_shdr symtab, strtab;
229 8d5f07fa bellard
    struct elf_sym *syms;
230 e80cfcfc bellard
    struct syminfo *s;
231 8d5f07fa bellard
    int nsyms, i;
232 8d5f07fa bellard
    char *str;
233 8d5f07fa bellard
234 8d5f07fa bellard
    /* Symbol table */
235 8d5f07fa bellard
    syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
236 8d5f07fa bellard
    if (!syms)
237 8d5f07fa bellard
        return;
238 420557e8 bellard
239 8d5f07fa bellard
    nsyms = symtab.sh_size / sizeof(struct elf_sym);
240 8d5f07fa bellard
    for (i = 0; i < nsyms; i++)
241 8d5f07fa bellard
        bswap_sym(&syms[i]);
242 8d5f07fa bellard
243 8d5f07fa bellard
    /* String table */
244 8d5f07fa bellard
    str = process_strtab(ehdr, fd, &strtab, &symtab);
245 8d5f07fa bellard
    if (!str)
246 8d5f07fa bellard
        goto error_freesyms;
247 8d5f07fa bellard
248 8d5f07fa bellard
    /* Commit */
249 e80cfcfc bellard
    s = qemu_mallocz(sizeof(*s));
250 e80cfcfc bellard
    s->disas_symtab = syms;
251 e80cfcfc bellard
    s->disas_num_syms = nsyms;
252 e80cfcfc bellard
    s->disas_strtab = str;
253 e80cfcfc bellard
    s->next = syminfos;
254 e80cfcfc bellard
    syminfos = s;
255 8d5f07fa bellard
    return;
256 8d5f07fa bellard
 error_freesyms:
257 8d5f07fa bellard
    qemu_free(syms);
258 8d5f07fa bellard
    return;
259 8d5f07fa bellard
}
260 420557e8 bellard
261 e80cfcfc bellard
int load_elf(const char *filename, uint8_t *addr)
262 8d5f07fa bellard
{
263 8d5f07fa bellard
    struct elfhdr ehdr;
264 8d5f07fa bellard
    struct elf_phdr phdr;
265 8d5f07fa bellard
    int retval, fd;
266 420557e8 bellard
267 8d5f07fa bellard
    fd = open(filename, O_RDONLY | O_BINARY);
268 8d5f07fa bellard
    if (fd < 0)
269 8d5f07fa bellard
        goto error;
270 420557e8 bellard
271 8d5f07fa bellard
    retval = read(fd, &ehdr, sizeof(ehdr));
272 8d5f07fa bellard
    if (retval < 0)
273 8d5f07fa bellard
        goto error;
274 420557e8 bellard
275 8d5f07fa bellard
    bswap_ehdr(&ehdr);
276 420557e8 bellard
277 8d5f07fa bellard
    if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
278 8d5f07fa bellard
        || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
279 e80cfcfc bellard
        || (ehdr.e_machine != EM_SPARC
280 e80cfcfc bellard
            && ehdr.e_machine != EM_SPARC32PLUS))
281 8d5f07fa bellard
        goto error;
282 420557e8 bellard
283 8d5f07fa bellard
    if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
284 8d5f07fa bellard
        goto error;
285 e80cfcfc bellard
    retval = read_program(fd, &phdr, addr, ehdr.e_entry);
286 8d5f07fa bellard
    if (retval < 0)
287 8d5f07fa bellard
        goto error;
288 420557e8 bellard
289 8d5f07fa bellard
    load_symbols(&ehdr, fd);
290 420557e8 bellard
291 8d5f07fa bellard
    close(fd);
292 8d5f07fa bellard
    return retval;
293 8d5f07fa bellard
 error:
294 8d5f07fa bellard
    close(fd);
295 8d5f07fa bellard
    return -1;
296 420557e8 bellard
}
297 420557e8 bellard
298 e80cfcfc bellard
int load_aout(const char *filename, uint8_t *addr)
299 420557e8 bellard
{
300 e80cfcfc bellard
    int fd, size, ret;
301 e80cfcfc bellard
    struct exec e;
302 e80cfcfc bellard
    uint32_t magic;
303 420557e8 bellard
304 420557e8 bellard
    fd = open(filename, O_RDONLY | O_BINARY);
305 420557e8 bellard
    if (fd < 0)
306 420557e8 bellard
        return -1;
307 e80cfcfc bellard
308 e80cfcfc bellard
    size = read(fd, &e, sizeof(e));
309 420557e8 bellard
    if (size < 0)
310 420557e8 bellard
        goto fail;
311 e80cfcfc bellard
312 e80cfcfc bellard
    bswap_ahdr(&e);
313 e80cfcfc bellard
314 e80cfcfc bellard
    magic = N_MAGIC(e);
315 e80cfcfc bellard
    switch (magic) {
316 e80cfcfc bellard
    case ZMAGIC:
317 e80cfcfc bellard
    case QMAGIC:
318 e80cfcfc bellard
    case OMAGIC:
319 e80cfcfc bellard
        lseek(fd, N_TXTOFF(e), SEEK_SET);
320 e80cfcfc bellard
        size = read(fd, addr, e.a_text + e.a_data);
321 e80cfcfc bellard
        if (size < 0)
322 e80cfcfc bellard
            goto fail;
323 e80cfcfc bellard
        break;
324 e80cfcfc bellard
    case NMAGIC:
325 e80cfcfc bellard
        lseek(fd, N_TXTOFF(e), SEEK_SET);
326 e80cfcfc bellard
        size = read(fd, addr, e.a_text);
327 e80cfcfc bellard
        if (size < 0)
328 e80cfcfc bellard
            goto fail;
329 e80cfcfc bellard
        ret = read(fd, addr + N_DATADDR(e), e.a_data);
330 e80cfcfc bellard
        if (ret < 0)
331 e80cfcfc bellard
            goto fail;
332 e80cfcfc bellard
        size += ret;
333 e80cfcfc bellard
        break;
334 e80cfcfc bellard
    default:
335 e80cfcfc bellard
        goto fail;
336 e80cfcfc bellard
    }
337 420557e8 bellard
    close(fd);
338 420557e8 bellard
    return size;
339 420557e8 bellard
 fail:
340 420557e8 bellard
    close(fd);
341 420557e8 bellard
    return -1;
342 420557e8 bellard
}