Commit 5fe141fd30d35516eac3674f7b62be51ba34543f

Authored by bellard
1 parent ce2f4b3c

generic ELF loader


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1831 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -270,7 +270,7 @@ ifeq ($(ARCH),alpha)
270 270 endif
271 271  
272 272 # must use static linking to avoid leaving stuff in virtual address space
273   -VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
  273 +VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
274 274 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
275 275 ifdef CONFIG_WIN32
276 276 VL_OBJS+=tap-win32.o
... ... @@ -332,9 +332,8 @@ ifeq ($(TARGET_ARCH), sparc64)
332 332 VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o
333 333 VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
334 334 VL_OBJS+= cirrus_vga.o parallel.o
335   -VL_OBJS+= magic-load.o
336 335 else
337   -VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o magic-load.o slavio_intctl.o
  336 +VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
338 337 VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
339 338 endif
340 339 endif
... ... @@ -459,6 +458,8 @@ op.o: op.c op_template.c op_mem.c
459 458 op_helper.o: op_helper_mem.c
460 459 endif
461 460  
  461 +loader.o: loader.c elf_ops.h
  462 +
462 463 %.o: %.c
463 464 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
464 465  
... ...
elf_ops.h 0 → 100644
  1 +static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
  2 +{
  3 + bswap16s(&ehdr->e_type); /* Object file type */
  4 + bswap16s(&ehdr->e_machine); /* Architecture */
  5 + bswap32s(&ehdr->e_version); /* Object file version */
  6 + bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
  7 + bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
  8 + bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
  9 + bswap32s(&ehdr->e_flags); /* Processor-specific flags */
  10 + bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
  11 + bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
  12 + bswap16s(&ehdr->e_phnum); /* Program header table entry count */
  13 + bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
  14 + bswap16s(&ehdr->e_shnum); /* Section header table entry count */
  15 + bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
  16 +}
  17 +
  18 +static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
  19 +{
  20 + bswap32s(&phdr->p_type); /* Segment type */
  21 + bswapSZs(&phdr->p_offset); /* Segment file offset */
  22 + bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
  23 + bswapSZs(&phdr->p_paddr); /* Segment physical address */
  24 + bswapSZs(&phdr->p_filesz); /* Segment size in file */
  25 + bswapSZs(&phdr->p_memsz); /* Segment size in memory */
  26 + bswap32s(&phdr->p_flags); /* Segment flags */
  27 + bswapSZs(&phdr->p_align); /* Segment alignment */
  28 +}
  29 +
  30 +static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
  31 +{
  32 + bswap32s(&shdr->sh_name);
  33 + bswap32s(&shdr->sh_type);
  34 + bswapSZs(&shdr->sh_flags);
  35 + bswapSZs(&shdr->sh_addr);
  36 + bswapSZs(&shdr->sh_offset);
  37 + bswapSZs(&shdr->sh_size);
  38 + bswap32s(&shdr->sh_link);
  39 + bswap32s(&shdr->sh_info);
  40 + bswapSZs(&shdr->sh_addralign);
  41 + bswapSZs(&shdr->sh_entsize);
  42 +}
  43 +
  44 +static void glue(bswap_sym, SZ)(struct elf_sym *sym)
  45 +{
  46 + bswap32s(&sym->st_name);
  47 + bswapSZs(&sym->st_value);
  48 + bswapSZs(&sym->st_size);
  49 + bswap16s(&sym->st_shndx);
  50 +}
  51 +
  52 +static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
  53 + int n, int type)
  54 +{
  55 + int i;
  56 + for(i=0;i<n;i++) {
  57 + if (shdr_table[i].sh_type == type)
  58 + return shdr_table + i;
  59 + }
  60 + return NULL;
  61 +}
  62 +
  63 +static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
  64 +{
  65 + struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
  66 + struct elf_sym *syms = NULL;
  67 +#if (SZ == 64)
  68 + struct elf32_sym *syms32 = NULL;
  69 +#endif
  70 + struct syminfo *s;
  71 + int nsyms, i;
  72 + char *str = NULL;
  73 +
  74 + shdr_table = load_at(fd, ehdr->e_shoff,
  75 + sizeof(struct elf_shdr) * ehdr->e_shnum);
  76 + if (!shdr_table)
  77 + return -1;
  78 +
  79 + if (must_swab) {
  80 + for (i = 0; i < ehdr->e_shnum; i++) {
  81 + glue(bswap_shdr, SZ)(shdr_table + i);
  82 + }
  83 + }
  84 +
  85 + symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
  86 + if (!symtab)
  87 + goto fail;
  88 + syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
  89 + if (!syms)
  90 + goto fail;
  91 +
  92 + nsyms = symtab->sh_size / sizeof(struct elf_sym);
  93 +#if (SZ == 64)
  94 + syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
  95 +#endif
  96 + for (i = 0; i < nsyms; i++) {
  97 + if (must_swab)
  98 + glue(bswap_sym, SZ)(&syms[i]);
  99 +#if (SZ == 64)
  100 + syms32[i].st_name = syms[i].st_name;
  101 + syms32[i].st_info = syms[i].st_info;
  102 + syms32[i].st_other = syms[i].st_other;
  103 + syms32[i].st_shndx = syms[i].st_shndx;
  104 + syms32[i].st_value = syms[i].st_value & 0xffffffff;
  105 + syms32[i].st_size = syms[i].st_size & 0xffffffff;
  106 +#endif
  107 + }
  108 + /* String table */
  109 + if (symtab->sh_link >= ehdr->e_shnum)
  110 + goto fail;
  111 + strtab = &shdr_table[symtab->sh_link];
  112 +
  113 + str = load_at(fd, strtab->sh_offset, strtab->sh_size);
  114 + if (!str)
  115 + goto fail;
  116 +
  117 + /* Commit */
  118 + s = qemu_mallocz(sizeof(*s));
  119 +#if (SZ == 64)
  120 + s->disas_symtab = syms32;
  121 + qemu_free(syms);
  122 +#else
  123 + s->disas_symtab = syms;
  124 +#endif
  125 + s->disas_num_syms = nsyms;
  126 + s->disas_strtab = str;
  127 + s->next = syminfos;
  128 + syminfos = s;
  129 + qemu_free(shdr_table);
  130 + return 0;
  131 + fail:
  132 +#if (SZ == 64)
  133 + qemu_free(syms32);
  134 +#endif
  135 + qemu_free(syms);
  136 + qemu_free(str);
  137 + qemu_free(shdr_table);
  138 + return -1;
  139 +}
  140 +
  141 +int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, int must_swab)
  142 +{
  143 + struct elfhdr ehdr;
  144 + struct elf_phdr *phdr = NULL, *ph;
  145 + int size, i, total_size;
  146 + elf_word mem_size, addr;
  147 + uint8_t *data;
  148 +
  149 + if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
  150 + goto fail;
  151 + if (must_swab) {
  152 + glue(bswap_ehdr, SZ)(&ehdr);
  153 + }
  154 +
  155 + glue(load_symbols, SZ)(&ehdr, fd, must_swab);
  156 +
  157 + size = ehdr.e_phnum * sizeof(phdr[0]);
  158 + lseek(fd, ehdr.e_phoff, SEEK_SET);
  159 + phdr = qemu_mallocz(size);
  160 + if (!phdr)
  161 + goto fail;
  162 + if (read(fd, phdr, size) != size)
  163 + goto fail;
  164 + if (must_swab) {
  165 + for(i = 0; i < ehdr.e_phnum; i++) {
  166 + ph = &phdr[i];
  167 + glue(bswap_phdr, SZ)(ph);
  168 + }
  169 + }
  170 +
  171 + total_size = 0;
  172 + for(i = 0; i < ehdr.e_phnum; i++) {
  173 + ph = &phdr[i];
  174 + if (ph->p_type == PT_LOAD) {
  175 + mem_size = ph->p_memsz;
  176 + /* XXX: avoid allocating */
  177 + data = qemu_mallocz(mem_size);
  178 + if (ph->p_filesz > 0) {
  179 + lseek(fd, ph->p_offset, SEEK_SET);
  180 + if (read(fd, data, ph->p_filesz) != ph->p_filesz)
  181 + goto fail;
  182 + }
  183 + addr = ph->p_vaddr + virt_to_phys_addend;
  184 +
  185 + cpu_physical_memory_write_rom(addr, data, mem_size);
  186 +
  187 + total_size += mem_size;
  188 +
  189 + qemu_free(data);
  190 + }
  191 + }
  192 + return total_size;
  193 + fail:
  194 + qemu_free(phdr);
  195 + return -1;
  196 +}
  197 +
... ...
loader.c 0 → 100644
  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 +}
... ...
... ... @@ -332,35 +332,6 @@ int strstart(const char *str, const char *val, const char **ptr)
332 332 return 1;
333 333 }
334 334  
335   -/* return the size or -1 if error */
336   -int get_image_size(const char *filename)
337   -{
338   - int fd, size;
339   - fd = open(filename, O_RDONLY | O_BINARY);
340   - if (fd < 0)
341   - return -1;
342   - size = lseek(fd, 0, SEEK_END);
343   - close(fd);
344   - return size;
345   -}
346   -
347   -/* return the size or -1 if error */
348   -int load_image(const char *filename, uint8_t *addr)
349   -{
350   - int fd, size;
351   - fd = open(filename, O_RDONLY | O_BINARY);
352   - if (fd < 0)
353   - return -1;
354   - size = lseek(fd, 0, SEEK_END);
355   - lseek(fd, 0, SEEK_SET);
356   - if (read(fd, addr, size) != size) {
357   - close(fd);
358   - return -1;
359   - }
360   - close(fd);
361   - return size;
362   -}
363   -
364 335 void cpu_outb(CPUState *env, int addr, int val)
365 336 {
366 337 #ifdef DEBUG_IOPORT
... ...
... ... @@ -87,8 +87,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
87 87  
88 88 void hw_error(const char *fmt, ...);
89 89  
90   -int get_image_size(const char *filename);
91   -int load_image(const char *filename, uint8_t *addr);
92 90 extern const char *bios_dir;
93 91  
94 92 void pstrcpy(char *buf, int buf_size, const char *str);
... ... @@ -871,8 +869,10 @@ void slavio_irq_info(void *opaque);
871 869 void slavio_pic_set_irq(void *opaque, int irq, int level);
872 870 void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu);
873 871  
874   -/* magic-load.c */
875   -int load_elf(const char *filename, uint8_t *addr);
  872 +/* loader.c */
  873 +int get_image_size(const char *filename);
  874 +int load_image(const char *filename, uint8_t *addr);
  875 +int load_elf(const char *filename, int64_t virt_to_phys_addend);
876 876 int load_aout(const char *filename, uint8_t *addr);
877 877  
878 878 /* slavio_timer.c */
... ...